mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
Initial attempt on access on commands
May change and will require more work / test / refactor
This commit is contained in:
parent
b4a430541d
commit
d7ad99f147
@ -28,6 +28,23 @@
|
|||||||
|
|
||||||
-type oauth_scope() :: atom().
|
-type oauth_scope() :: atom().
|
||||||
|
|
||||||
|
%% ejabberd_commands OAuth ReST ACL definition:
|
||||||
|
%% Two fields exist that are used to control access on a command from ReST API:
|
||||||
|
%% 1. Policy
|
||||||
|
%% If policy is:
|
||||||
|
%% - restricted: command is not exposed as OAuth Rest API.
|
||||||
|
%% - admin: Command is allowed for user that have Admin Rest command enabled by access rule: commands_admin_access
|
||||||
|
%% - user: Command might be called by any server user.
|
||||||
|
%% - open: Command can be called by anyone.
|
||||||
|
%%
|
||||||
|
%% Policy is just used to control who can call the command. A specific additional access rules can be performed, as
|
||||||
|
%% defined by access option.
|
||||||
|
%% Access option can be a list of:
|
||||||
|
%% - {Module, accessName, DefaultValue}: Reference and existing module access to limit who can use the command.
|
||||||
|
%% - AccessRule name: direct name of the access rule to check in config file.
|
||||||
|
%% TODO: Access option could be atom command (not a list). In the case, User performing the command, will be added as first parameter
|
||||||
|
%% to command, so that the command can perform additional check.
|
||||||
|
|
||||||
-record(ejabberd_commands,
|
-record(ejabberd_commands,
|
||||||
{name :: atom(),
|
{name :: atom(),
|
||||||
tags = [] :: [atom()] | '_' | '$2',
|
tags = [] :: [atom()] | '_' | '$2',
|
||||||
@ -38,7 +55,8 @@
|
|||||||
function :: atom() | '_',
|
function :: atom() | '_',
|
||||||
args = [] :: [aterm()] | '_' | '$1' | '$2',
|
args = [] :: [aterm()] | '_' | '$1' | '$2',
|
||||||
policy = restricted :: open | restricted | admin | user,
|
policy = restricted :: open | restricted | admin | user,
|
||||||
access_rules = [] :: [atom()],
|
%% access is: [accessRuleName] or [{Module, AccessOption, DefaultAccessRuleName}]
|
||||||
|
access = [] :: [{atom(),atom(),atom()}|atom()],
|
||||||
result = {res, rescode} :: rterm() | '_' | '$2',
|
result = {res, rescode} :: rterm() | '_' | '$2',
|
||||||
args_desc = none :: none | [string()] | '_',
|
args_desc = none :: none | [string()] | '_',
|
||||||
result_desc = none :: none | string() | '_',
|
result_desc = none :: none | string() | '_',
|
||||||
@ -55,7 +73,7 @@
|
|||||||
function :: atom(),
|
function :: atom(),
|
||||||
args :: [aterm()],
|
args :: [aterm()],
|
||||||
policy :: open | restricted | admin | user,
|
policy :: open | restricted | admin | user,
|
||||||
access_rules :: [atom()],
|
access :: [{atom(),atom(),atom()}|atom()],
|
||||||
result :: rterm()}.
|
result :: rterm()}.
|
||||||
|
|
||||||
%% @type ejabberd_commands() = #ejabberd_commands{
|
%% @type ejabberd_commands() = #ejabberd_commands{
|
||||||
|
@ -130,7 +130,7 @@ get_commands_spec() ->
|
|||||||
#ejabberd_commands{name = register, tags = [accounts],
|
#ejabberd_commands{name = register, tags = [accounts],
|
||||||
desc = "Register a user",
|
desc = "Register a user",
|
||||||
policy = admin,
|
policy = admin,
|
||||||
access_rules = [configure],
|
access = [{mod_register, access, configure}],
|
||||||
module = ?MODULE, function = register,
|
module = ?MODULE, function = register,
|
||||||
args = [{user, binary}, {host, binary}, {password, binary}],
|
args = [{user, binary}, {host, binary}, {password, binary}],
|
||||||
result = {res, restuple}},
|
result = {res, restuple}},
|
||||||
|
@ -319,8 +319,8 @@ list_commands() ->
|
|||||||
list_commands(Version) ->
|
list_commands(Version) ->
|
||||||
Commands = get_commands_definition(Version),
|
Commands = get_commands_definition(Version),
|
||||||
[{Name, Args, Desc} || #ejabberd_commands{name = Name,
|
[{Name, Args, Desc} || #ejabberd_commands{name = Name,
|
||||||
args = Args,
|
args = Args,
|
||||||
desc = Desc} <- Commands].
|
desc = Desc} <- Commands].
|
||||||
|
|
||||||
|
|
||||||
-spec list_commands_policy(integer()) ->
|
-spec list_commands_policy(integer()) ->
|
||||||
@ -331,10 +331,10 @@ list_commands(Version) ->
|
|||||||
list_commands_policy(Version) ->
|
list_commands_policy(Version) ->
|
||||||
Commands = get_commands_definition(Version),
|
Commands = get_commands_definition(Version),
|
||||||
[{Name, Args, Desc, Policy} ||
|
[{Name, Args, Desc, Policy} ||
|
||||||
#ejabberd_commands{name = Name,
|
#ejabberd_commands{name = Name,
|
||||||
args = Args,
|
args = Args,
|
||||||
desc = Desc,
|
desc = Desc,
|
||||||
policy = Policy} <- Commands].
|
policy = Policy} <- Commands].
|
||||||
|
|
||||||
-spec get_command_format(atom()) -> {[aterm()], rterm()}.
|
-spec get_command_format(atom()) -> {[aterm()], rterm()}.
|
||||||
|
|
||||||
@ -356,14 +356,14 @@ get_command_format(Name, Auth, Version) ->
|
|||||||
Admin = is_admin(Name, Auth, #{}),
|
Admin = is_admin(Name, Auth, #{}),
|
||||||
#ejabberd_commands{args = Args,
|
#ejabberd_commands{args = Args,
|
||||||
result = Result,
|
result = Result,
|
||||||
policy = Policy} =
|
policy = Policy} =
|
||||||
get_command_definition(Name, Version),
|
get_command_definition(Name, Version),
|
||||||
case Policy of
|
case Policy of
|
||||||
user when Admin;
|
user when Admin;
|
||||||
Auth == noauth ->
|
Auth == noauth ->
|
||||||
{[{user, binary}, {server, binary} | Args], Result};
|
{[{user, binary}, {server, binary} | Args], Result};
|
||||||
_ ->
|
_ ->
|
||||||
{Args, Result}
|
{Args, Result}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec get_command_policy_and_scope(atom()) -> {ok, open|user|admin|restricted, [oauth_scope()]} | {error, command_not_found}.
|
-spec get_command_policy_and_scope(atom()) -> {ok, open|user|admin|restricted, [oauth_scope()]} | {error, command_not_found}.
|
||||||
@ -394,16 +394,16 @@ get_command_definition(Name) ->
|
|||||||
%% @doc Get the definition record of a command in a given API version.
|
%% @doc Get the definition record of a command in a given API version.
|
||||||
get_command_definition(Name, Version) ->
|
get_command_definition(Name, Version) ->
|
||||||
case lists:reverse(
|
case lists:reverse(
|
||||||
lists:sort(
|
lists:sort(
|
||||||
mnesia:dirty_select(
|
mnesia:dirty_select(
|
||||||
ejabberd_commands,
|
ejabberd_commands,
|
||||||
ets:fun2ms(
|
ets:fun2ms(
|
||||||
fun(#ejabberd_commands{name = N, version = V} = C)
|
fun(#ejabberd_commands{name = N, version = V} = C)
|
||||||
when N == Name, V =< Version ->
|
when N == Name, V =< Version ->
|
||||||
{V, C}
|
{V, C}
|
||||||
end)))) of
|
end)))) of
|
||||||
[{_, Command} | _ ] -> Command;
|
[{_, Command} | _ ] -> Command;
|
||||||
_E -> throw(unknown_command)
|
_E -> throw(unknown_command)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec get_commands_definition(integer()) -> [ejabberd_commands()].
|
-spec get_commands_definition(integer()) -> [ejabberd_commands()].
|
||||||
@ -411,20 +411,20 @@ get_command_definition(Name, Version) ->
|
|||||||
% @doc Returns all commands for a given API version
|
% @doc Returns all commands for a given API version
|
||||||
get_commands_definition(Version) ->
|
get_commands_definition(Version) ->
|
||||||
L = lists:reverse(
|
L = lists:reverse(
|
||||||
lists:sort(
|
lists:sort(
|
||||||
mnesia:dirty_select(
|
mnesia:dirty_select(
|
||||||
ejabberd_commands,
|
ejabberd_commands,
|
||||||
ets:fun2ms(
|
ets:fun2ms(
|
||||||
fun(#ejabberd_commands{name = Name, version = V} = C)
|
fun(#ejabberd_commands{name = Name, version = V} = C)
|
||||||
when V =< Version ->
|
when V =< Version ->
|
||||||
{Name, V, C}
|
{Name, V, C}
|
||||||
end)))),
|
end)))),
|
||||||
F = fun({_Name, _V, Command}, []) ->
|
F = fun({_Name, _V, Command}, []) ->
|
||||||
[Command];
|
[Command];
|
||||||
({Name, _V, _Command}, [#ejabberd_commands{name=Name}|_T] = Acc) ->
|
({Name, _V, _Command}, [#ejabberd_commands{name=Name}|_T] = Acc) ->
|
||||||
Acc;
|
Acc;
|
||||||
({_Name, _V, Command}, Acc) -> [Command | Acc]
|
({_Name, _V, Command}, Acc) -> [Command | Acc]
|
||||||
end,
|
end,
|
||||||
lists:foldl(F, [], L).
|
lists:foldl(F, [], L).
|
||||||
|
|
||||||
%% @spec (Name::atom(), Arguments) -> ResultTerm
|
%% @spec (Name::atom(), Arguments) -> ResultTerm
|
||||||
@ -433,7 +433,7 @@ get_commands_definition(Version) ->
|
|||||||
%% @doc Execute a command.
|
%% @doc Execute a command.
|
||||||
%% Can return the following exceptions:
|
%% Can return the following exceptions:
|
||||||
%% command_unknown | account_unprivileged | invalid_account_data |
|
%% command_unknown | account_unprivileged | invalid_account_data |
|
||||||
%% no_auth_provided
|
%% no_auth_provided | access_rules_unauthorized
|
||||||
execute_command(Name, Arguments) ->
|
execute_command(Name, Arguments) ->
|
||||||
execute_command(Name, Arguments, ?DEFAULT_VERSION).
|
execute_command(Name, Arguments, ?DEFAULT_VERSION).
|
||||||
|
|
||||||
@ -505,7 +505,7 @@ execute_command(AccessCommands1, Auth1, Name, Arguments, Version, CallerInfo) ->
|
|||||||
end,
|
end,
|
||||||
TokenJID = oauth_token_user(Auth1),
|
TokenJID = oauth_token_user(Auth1),
|
||||||
Command = get_command_definition(Name, Version),
|
Command = get_command_definition(Name, Version),
|
||||||
AccessCommands = get_access_commands(AccessCommands1, Version),
|
AccessCommands = get_all_access_commands(AccessCommands1),
|
||||||
case check_access_commands(AccessCommands, Auth, Name, Command, Arguments, CallerInfo) of
|
case check_access_commands(AccessCommands, Auth, Name, Command, Arguments, CallerInfo) of
|
||||||
ok -> execute_check_policy(Auth, TokenJID, Command, Arguments)
|
ok -> execute_check_policy(Auth, TokenJID, Command, Arguments)
|
||||||
end.
|
end.
|
||||||
@ -530,15 +530,22 @@ execute_check_policy(
|
|||||||
{User, Server, _, _}, JID, #ejabberd_commands{policy = user} = Command, Arguments) ->
|
{User, Server, _, _}, JID, #ejabberd_commands{policy = user} = Command, Arguments) ->
|
||||||
execute_check_access(JID, Command, [User, Server | Arguments]).
|
execute_check_access(JID, Command, [User, Server | Arguments]).
|
||||||
|
|
||||||
execute_check_access(_FromJID, #ejabberd_commands{access_rules = []} = Command, Arguments) ->
|
execute_check_access(_FromJID, #ejabberd_commands{access = []} = Command, Arguments) ->
|
||||||
do_execute_command(Command, Arguments);
|
do_execute_command(Command, Arguments);
|
||||||
execute_check_access(FromJID, #ejabberd_commands{access_rules = Rules} = Command, Arguments) ->
|
execute_check_access(FromJID, #ejabberd_commands{access = AccessRefs} = Command, Arguments) ->
|
||||||
%% TODO Review: Do we have smarter / better way to check rule on other Host than global ?
|
%% TODO Review: Do we have smarter / better way to check rule on other Host than global ?
|
||||||
case acl:any_rules_allowed(global, Rules, FromJID) of
|
Host = global,
|
||||||
|
Rules = lists:map(fun({Mod, AccessName, Default}) ->
|
||||||
|
gen_mod:get_module_opt(Host, Mod,
|
||||||
|
AccessName, fun(A) -> A end, Default);
|
||||||
|
(Default) ->
|
||||||
|
Default
|
||||||
|
end, AccessRefs),
|
||||||
|
case acl:any_rules_allowed(Host, Rules, FromJID) of
|
||||||
true ->
|
true ->
|
||||||
do_execute_command(Command, Arguments);
|
do_execute_command(Command, Arguments);
|
||||||
false ->
|
false ->
|
||||||
{error, access_rules_unauthorized}
|
throw({error, access_rules_unauthorized})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_execute_command(Command, Arguments) ->
|
do_execute_command(Command, Arguments) ->
|
||||||
@ -611,31 +618,31 @@ check_access_commands(AccessCommands, Auth, Method, Command1, Arguments, CallerI
|
|||||||
Command1
|
Command1
|
||||||
end,
|
end,
|
||||||
AccessCommandsAllowed =
|
AccessCommandsAllowed =
|
||||||
lists:filter(
|
lists:filter(
|
||||||
fun({Access, Commands, ArgumentRestrictions}) ->
|
fun({Access, Commands, ArgumentRestrictions}) ->
|
||||||
case check_access(Command, Access, Auth, CallerInfo) of
|
case check_access(Command, Access, Auth, CallerInfo) of
|
||||||
true ->
|
true ->
|
||||||
check_access_command(Commands, Command,
|
check_access_command(Commands, Command,
|
||||||
ArgumentRestrictions,
|
ArgumentRestrictions,
|
||||||
Method, Arguments);
|
Method, Arguments);
|
||||||
false ->
|
false ->
|
||||||
false
|
false
|
||||||
end;
|
end;
|
||||||
({Access, Commands}) ->
|
({Access, Commands}) ->
|
||||||
ArgumentRestrictions = [],
|
ArgumentRestrictions = [],
|
||||||
case check_access(Command, Access, Auth, CallerInfo) of
|
case check_access(Command, Access, Auth, CallerInfo) of
|
||||||
true ->
|
true ->
|
||||||
check_access_command(Commands, Command,
|
check_access_command(Commands, Command,
|
||||||
ArgumentRestrictions,
|
ArgumentRestrictions,
|
||||||
Method, Arguments);
|
Method, Arguments);
|
||||||
false ->
|
false ->
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
AccessCommands),
|
AccessCommands),
|
||||||
case AccessCommandsAllowed of
|
case AccessCommandsAllowed of
|
||||||
[] -> throw({error, account_unprivileged});
|
[] -> throw({error, account_unprivileged});
|
||||||
L when is_list(L) -> ok
|
L when is_list(L) -> ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec check_auth(ejabberd_commands(), noauth) -> noauth_provided;
|
-spec check_auth(ejabberd_commands(), noauth) -> noauth_provided;
|
||||||
@ -699,9 +706,9 @@ check_access2(Access, AccessInfo, Server) ->
|
|||||||
check_access_command(Commands, Command, ArgumentRestrictions,
|
check_access_command(Commands, Command, ArgumentRestrictions,
|
||||||
Method, Arguments) ->
|
Method, Arguments) ->
|
||||||
case Commands==all orelse lists:member(Method, Commands) of
|
case Commands==all orelse lists:member(Method, Commands) of
|
||||||
true -> check_access_arguments(Command, ArgumentRestrictions,
|
true -> check_access_arguments(Command, ArgumentRestrictions,
|
||||||
Arguments);
|
Arguments);
|
||||||
false -> false
|
false -> false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
check_access_arguments(Command, ArgumentRestrictions, Arguments) ->
|
check_access_arguments(Command, ArgumentRestrictions, Arguments) ->
|
||||||
@ -724,6 +731,10 @@ tag_arguments(ArgsDefs, Args) ->
|
|||||||
Args).
|
Args).
|
||||||
|
|
||||||
|
|
||||||
|
%% Get commands for all version
|
||||||
|
get_all_access_commands(AccessCommands) ->
|
||||||
|
get_access_commands(AccessCommands, ?DEFAULT_VERSION).
|
||||||
|
|
||||||
get_access_commands(undefined, Version) ->
|
get_access_commands(undefined, Version) ->
|
||||||
Cmds = get_commands(Version),
|
Cmds = get_commands(Version),
|
||||||
[{?POLICY_ACCESS, Cmds, []}];
|
[{?POLICY_ACCESS, Cmds, []}];
|
||||||
@ -736,7 +747,7 @@ get_commands(Version) ->
|
|||||||
Opts0 = ejabberd_config:get_option(
|
Opts0 = ejabberd_config:get_option(
|
||||||
commands,
|
commands,
|
||||||
fun(V) when is_list(V) -> V end,
|
fun(V) when is_list(V) -> V end,
|
||||||
[]),
|
[]),
|
||||||
Opts = lists:map(fun(V) when is_tuple(V) -> [V]; (V) -> V end, Opts0),
|
Opts = lists:map(fun(V) when is_tuple(V) -> [V]; (V) -> V end, Opts0),
|
||||||
CommandsList = list_commands_policy(Version),
|
CommandsList = list_commands_policy(Version),
|
||||||
OpenCmds = [N || {N, _, _, open} <- CommandsList],
|
OpenCmds = [N || {N, _, _, open} <- CommandsList],
|
||||||
@ -746,27 +757,29 @@ get_commands(Version) ->
|
|||||||
Cmds =
|
Cmds =
|
||||||
lists:foldl(
|
lists:foldl(
|
||||||
fun([{add_commands, L}], Acc) ->
|
fun([{add_commands, L}], Acc) ->
|
||||||
Cmds = case L of
|
Cmds = expand_commands(L, OpenCmds, UserCmds, AdminCmds, RestrictedCmds),
|
||||||
open -> OpenCmds;
|
|
||||||
restricted -> RestrictedCmds;
|
|
||||||
admin -> AdminCmds;
|
|
||||||
user -> UserCmds;
|
|
||||||
_ when is_list(L) -> L
|
|
||||||
end,
|
|
||||||
lists:usort(Cmds ++ Acc);
|
lists:usort(Cmds ++ Acc);
|
||||||
([{remove_commands, L}], Acc) ->
|
([{remove_commands, L}], Acc) ->
|
||||||
Cmds = case L of
|
Cmds = expand_commands(L, OpenCmds, UserCmds, AdminCmds, RestrictedCmds),
|
||||||
open -> OpenCmds;
|
|
||||||
restricted -> RestrictedCmds;
|
|
||||||
admin -> AdminCmds;
|
|
||||||
user -> UserCmds;
|
|
||||||
_ when is_list(L) -> L
|
|
||||||
end,
|
|
||||||
Acc -- Cmds;
|
Acc -- Cmds;
|
||||||
(_, Acc) -> Acc
|
(_, Acc) -> Acc
|
||||||
end, AdminCmds ++ UserCmds, Opts),
|
end, [], Opts),
|
||||||
Cmds.
|
Cmds.
|
||||||
|
|
||||||
|
expand_commands(L, OpenCmds, UserCmds, AdminCmds, RestrictedCmds) when is_list(L) ->
|
||||||
|
lists:foldl(fun(El, Acc) ->
|
||||||
|
expand_commands(El, OpenCmds, UserCmds, AdminCmds, RestrictedCmds) ++ Acc
|
||||||
|
end, [], L);
|
||||||
|
expand_commands(El, OpenCmds, UserCmds, AdminCmds, RestrictedCmds) ->
|
||||||
|
case El of
|
||||||
|
open -> OpenCmds;
|
||||||
|
restricted -> RestrictedCmds;
|
||||||
|
admin -> AdminCmds;
|
||||||
|
user -> UserCmds;
|
||||||
|
_ -> [El]
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
oauth_token_user(noauth) ->
|
oauth_token_user(noauth) ->
|
||||||
undefined;
|
undefined;
|
||||||
oauth_token_user(admin) ->
|
oauth_token_user(admin) ->
|
||||||
|
@ -136,8 +136,7 @@ check_permissions(Request, Command) ->
|
|||||||
{ok, CommandPolicy, Scope} = ejabberd_commands:get_command_policy_and_scope(Call),
|
{ok, CommandPolicy, Scope} = ejabberd_commands:get_command_policy_and_scope(Call),
|
||||||
check_permissions2(Request, Call, CommandPolicy, Scope);
|
check_permissions2(Request, Call, CommandPolicy, Scope);
|
||||||
_ ->
|
_ ->
|
||||||
%% TODO Should this be a 404 or 400 instead of 401 ?
|
json_error(404, 40, <<"Endpoint not found.">>)
|
||||||
unauthorized_response()
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
check_permissions2(#request{auth = HTTPAuth, headers = Headers}, Call, _, ScopeList)
|
check_permissions2(#request{auth = HTTPAuth, headers = Headers}, Call, _, ScopeList)
|
||||||
@ -269,10 +268,10 @@ get_api_version(#request{path = Path}) ->
|
|||||||
get_api_version(lists:reverse(Path));
|
get_api_version(lists:reverse(Path));
|
||||||
get_api_version([<<"v", String/binary>> | Tail]) ->
|
get_api_version([<<"v", String/binary>> | Tail]) ->
|
||||||
case catch jlib:binary_to_integer(String) of
|
case catch jlib:binary_to_integer(String) of
|
||||||
N when is_integer(N) ->
|
N when is_integer(N) ->
|
||||||
N;
|
N;
|
||||||
_ ->
|
_ ->
|
||||||
get_api_version(Tail)
|
get_api_version(Tail)
|
||||||
end;
|
end;
|
||||||
get_api_version([_Head | Tail]) ->
|
get_api_version([_Head | Tail]) ->
|
||||||
get_api_version(Tail);
|
get_api_version(Tail);
|
||||||
@ -318,6 +317,8 @@ handle(Call, Auth, Args, Version, IP) when is_atom(Call), is_list(Args) ->
|
|||||||
{401, iolist_to_binary(Msg)};
|
{401, iolist_to_binary(Msg)};
|
||||||
throw:{error, account_unprivileged} ->
|
throw:{error, account_unprivileged} ->
|
||||||
{403, 31, <<"Command need to be run with admin priviledge.">>};
|
{403, 31, <<"Command need to be run with admin priviledge.">>};
|
||||||
|
throw:{error, access_rules_unauthorized} ->
|
||||||
|
{403, 32, <<"AccessRules: Account associated to token does not have the right to perform the operation.">>};
|
||||||
throw:{invalid_parameter, Msg} ->
|
throw:{invalid_parameter, Msg} ->
|
||||||
{400, iolist_to_binary(Msg)};
|
{400, iolist_to_binary(Msg)};
|
||||||
throw:{error, Why} when is_atom(Why) ->
|
throw:{error, Why} when is_atom(Why) ->
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
#
|
#
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
## TODO Fix next test error: add admin user ACL
|
||||||
|
|
||||||
defmodule EjabberdCommandsMockTest do
|
defmodule EjabberdCommandsMockTest do
|
||||||
use ExUnit.Case, async: false
|
use ExUnit.Case, async: false
|
||||||
|
|
||||||
@ -44,6 +46,9 @@ defmodule EjabberdCommandsMockTest do
|
|||||||
_ -> :ok
|
_ -> :ok
|
||||||
end
|
end
|
||||||
:mnesia.start
|
:mnesia.start
|
||||||
|
:ok = :jid.start
|
||||||
|
:ok = :ejabberd_config.start(["domain1", "domain2"], [])
|
||||||
|
:ok = :acl.start
|
||||||
EjabberdOauthMock.init
|
EjabberdOauthMock.init
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
@ -313,7 +318,6 @@ defmodule EjabberdCommandsMockTest do
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
test "API command with admin policy" do
|
test "API command with admin policy" do
|
||||||
mock_commands_config
|
mock_commands_config
|
||||||
|
|
||||||
@ -393,6 +397,40 @@ defmodule EjabberdCommandsMockTest do
|
|||||||
assert :meck.validate @module
|
assert :meck.validate @module
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "Commands can perform extra check on access" do
|
||||||
|
mock_commands_config
|
||||||
|
|
||||||
|
command_name = :test
|
||||||
|
function = :test_command
|
||||||
|
command = ejabberd_commands(name: command_name,
|
||||||
|
args: [{:user, :binary}, {:host, :binary}],
|
||||||
|
access: [:basic_rule_1],
|
||||||
|
module: @module,
|
||||||
|
function: function,
|
||||||
|
policy: :open)
|
||||||
|
:meck.expect(@module, function,
|
||||||
|
fn(user, domain) when is_binary(user) and is_binary(domain) ->
|
||||||
|
{user, domain}
|
||||||
|
end)
|
||||||
|
assert :ok == :ejabberd_commands.register_commands [command]
|
||||||
|
|
||||||
|
:acl.add(:global, :basic_acl_1, {:user, @user})
|
||||||
|
:acl.add_access(:global, :basic_rule_1, [{:allow, [{:acl, :basic_acl_1}]}])
|
||||||
|
|
||||||
|
assert {@user, @domain} ==
|
||||||
|
:ejabberd_commands.execute_command(:undefined,
|
||||||
|
{@user, @domain,
|
||||||
|
@userpass, false},
|
||||||
|
command_name,
|
||||||
|
[@user, @domain])
|
||||||
|
assert {@user, @domain} ==
|
||||||
|
:ejabberd_commands.execute_command(:undefined,
|
||||||
|
{@admin, @domain,
|
||||||
|
@adminpass, false},
|
||||||
|
command_name,
|
||||||
|
[@user, @domain])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
# Utils
|
# Utils
|
||||||
@ -412,7 +450,7 @@ defmodule EjabberdCommandsMockTest do
|
|||||||
end)
|
end)
|
||||||
:meck.expect(:ejabberd_config, :get_myhosts,
|
:meck.expect(:ejabberd_config, :get_myhosts,
|
||||||
fn() -> [@domain] end)
|
fn() -> [@domain] end)
|
||||||
:meck.new :acl
|
:meck.new :acl #, [:passthrough]
|
||||||
:meck.expect(:acl, :access_matches,
|
:meck.expect(:acl, :access_matches,
|
||||||
fn(:commands_admin_access, info, _scope) ->
|
fn(:commands_admin_access, info, _scope) ->
|
||||||
case info do
|
case info do
|
||||||
|
Loading…
Reference in New Issue
Block a user