25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-20 17:27:00 +01:00

Add support for backwards compatibility in command argument names (#2908)

This commit is contained in:
Badlop 2019-06-18 11:09:35 +02:00
parent ad98d4a515
commit fb77e2e8c0
5 changed files with 40 additions and 16 deletions

View File

@ -59,6 +59,7 @@
%% access is: [accessRuleName] or [{Module, AccessOption, DefaultAccessRuleName}]
access = [] :: [{atom(),atom(),atom()}|atom()],
result = {res, rescode} :: rterm() | '_' | '$2',
args_rename = [] :: [{atom(),atom()}],
args_desc = none :: none | [string()] | '_',
result_desc = none :: none | string() | '_',
args_example = none :: none | [any()] | '_',

View File

@ -353,7 +353,7 @@ list_commands(Version) ->
args = Args,
desc = Desc} <- Commands].
-spec get_command_format(atom()) -> {[aterm()], rterm()}.
-spec get_command_format(atom()) -> {[aterm()], [{atom(),atom()}], rterm()}.
%% @doc Get the format of arguments and result of a command.
get_command_format(Name) ->
@ -363,19 +363,20 @@ get_command_format(Name, Version) when is_integer(Version) ->
get_command_format(Name, Auth) ->
get_command_format(Name, Auth, ?DEFAULT_VERSION).
-spec get_command_format(atom(), noauth | admin | auth(), integer()) -> {[aterm()], rterm()}.
-spec get_command_format(atom(), noauth | admin | auth(), integer()) -> {[aterm()], [{atom(),atom()}], rterm()}.
get_command_format(Name, Auth, Version) ->
Admin = is_admin(Name, Auth, #{}),
#ejabberd_commands{args = Args,
result = Result,
args_rename = Rename,
policy = Policy} =
get_command_definition(Name, Version),
case Policy of
user when Admin;
Auth == noauth ->
{[{user, binary}, {server, binary} | Args], Result};
{[{user, binary}, {server, binary} | Args], Rename, Result};
_ ->
{Args, Result}
{Args, Rename, Result}
end.
-spec get_command_definition(atom()) -> ejabberd_commands().

View File

@ -340,7 +340,7 @@ call_command([CmdString | Args], Auth, _AccessCommands, Version) ->
CmdStringU = ejabberd_regexp:greplace(
list_to_binary(CmdString), <<"-">>, <<"_">>),
Command = list_to_atom(binary_to_list(CmdStringU)),
{ArgsFormat, ResultFormat} = ejabberd_commands:get_command_format(Command, Auth, Version),
{ArgsFormat, _, ResultFormat} = ejabberd_commands:get_command_format(Command, Auth, Version),
case (catch format_args(Args, ArgsFormat)) of
ArgsFormatted when is_list(ArgsFormatted) ->
CI = case Auth of
@ -484,7 +484,7 @@ get_list_commands(Version) ->
%% Return: {string(), [string()], string()}
tuple_command_help({Name, _Args, Desc}) ->
{Args, _} = ejabberd_commands:get_command_format(Name, admin),
{Args, _, _} = ejabberd_commands:get_command_format(Name, admin),
Arguments = [atom_to_list(ArgN) || {ArgN, _ArgF} <- Args],
Prepend = case is_supported_args(Args) of
true -> "";
@ -796,7 +796,7 @@ print_usage_command2(Cmd, C, MaxC, ShCode) ->
NameFmt = [" ", ?B("Command Name"), ": ", Cmd, "\n"],
%% Initial indentation of result is 13 = length(" Arguments: ")
{ArgsDef, _} = ejabberd_commands:get_command_format(
{ArgsDef, _, _} = ejabberd_commands:get_command_format(
C#ejabberd_commands.name, admin),
Args = [format_usage_ctype(ArgDef, 13) || ArgDef <- ArgsDef],
ArgsMargin = lists:duplicate(13, $\s),

View File

@ -339,9 +339,9 @@ handler(State, {call, Command, []}) ->
handler(State, {call, Command, [{struct, []}]});
handler(State,
{call, Command, [{struct, AttrL}]}) ->
{ArgsF, ResultF} = ejabberd_commands:get_command_format(Command, State#state.auth),
{ArgsF, ArgsR, ResultF} = ejabberd_commands:get_command_format(Command, State#state.auth),
try_do_command(State#state.access_commands,
State#state.auth, Command, AttrL, ArgsF, ResultF);
State#state.auth, Command, AttrL, ArgsF, ArgsR, ResultF);
%% If no other guard matches
handler(_State, Payload) ->
build_fault_response(-112, "Unknown call: ~p",
@ -352,9 +352,9 @@ handler(_State, Payload) ->
%% -----------------------------
try_do_command(AccessCommands, Auth, Command, AttrL,
ArgsF, ResultF) ->
ArgsF, ArgsR, ResultF) ->
try do_command(AccessCommands, Auth, Command, AttrL,
ArgsF, ResultF)
ArgsF, ArgsR, ResultF)
of
{command_result, ResultFormatted} ->
{false, {response, [ResultFormatted]}}
@ -389,14 +389,25 @@ build_fault_response(Code, ParseString, ParseArgs) ->
?WARNING_MSG(FaultString, []),
{false, {response, {fault, Code, list_to_binary(FaultString)}}}.
do_command(AccessCommands, Auth, Command, AttrL, ArgsF,
do_command(AccessCommands, Auth, Command, AttrL, ArgsF, ArgsR,
ResultF) ->
ArgsFormatted = format_args(AttrL, ArgsF),
ArgsFormatted = format_args(rename_old_args(AttrL, ArgsR), ArgsF),
Auth2 = Auth#{extra_permissions => AccessCommands},
Result = ejabberd_commands:execute_command2(Command, ArgsFormatted, Auth2),
ResultFormatted = format_result(Result, ResultF),
{command_result, ResultFormatted}.
rename_old_args(Args, []) ->
Args;
rename_old_args(Args, [{OldName, NewName} | ArgsR]) ->
Args2 = case lists:keytake(OldName, 1, Args) of
{value, {OldName, Value}, ArgsTail} ->
[{NewName, Value} | ArgsTail];
false ->
Args
end,
rename_old_args(Args2, ArgsR).
%%-----------------------------
%% Format arguments
%%-----------------------------

View File

@ -304,8 +304,8 @@ handle(Call, Auth, Args, Version) when is_atom(Call), is_list(Args) ->
end.
handle2(Call, Auth, Args, Version) when is_atom(Call), is_list(Args) ->
{ArgsF, _ResultF} = ejabberd_commands:get_command_format(Call, Auth, Version),
ArgsFormatted = format_args(Call, Args, ArgsF),
{ArgsF, ArgsR, _ResultF} = ejabberd_commands:get_command_format(Call, Auth, Version),
ArgsFormatted = format_args(Call, rename_old_args(Args, ArgsR), ArgsF),
case ejabberd_commands:execute_command2(Call, ArgsFormatted, Auth, Version) of
{error, Error} ->
throw(Error);
@ -313,6 +313,17 @@ handle2(Call, Auth, Args, Version) when is_atom(Call), is_list(Args) ->
format_command_result(Call, Auth, Res, Version)
end.
rename_old_args(Args, []) ->
Args;
rename_old_args(Args, [{OldName, NewName} | ArgsR]) ->
Args2 = case lists:keytake(OldName, 1, Args) of
{value, {OldName, Value}, ArgsTail} ->
[{NewName, Value} | ArgsTail];
false ->
Args
end,
rename_old_args(Args2, ArgsR).
get_elem_delete(Call, A, L, F) ->
case proplists:get_all_values(A, L) of
[Value] -> {Value, proplists:delete(A, L)};
@ -422,7 +433,7 @@ process_unicode_codepoints(Str) ->
%% ----------------
format_command_result(Cmd, Auth, Result, Version) ->
{_, ResultFormat} = ejabberd_commands:get_command_format(Cmd, Auth, Version),
{_, _, ResultFormat} = ejabberd_commands:get_command_format(Cmd, Auth, Version),
case {ResultFormat, Result} of
{{_, rescode}, V} when V == true; V == ok ->
{200, 0};