mirror of
https://github.com/processone/ejabberd
synced 2025-10-03 09:49:18 +02:00
mod_configure: Add option 'access' to let configure the access name
This commit is contained in:
parent
6151674e64
commit
aa78362c7f
2 changed files with 73 additions and 25 deletions
|
@ -1,7 +1,7 @@
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
%%% File : mod_configure.erl
|
%%% File : mod_configure.erl
|
||||||
%%% Author : Alexey Shchepin <alexey@process-one.net>
|
%%% Author : Alexey Shchepin <alexey@process-one.net>
|
||||||
%%% Purpose : Support for online configuration of ejabberd
|
%%% Purpose : Support for online configuration of ejabberd using XEP-0050
|
||||||
%%% Created : 19 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
%%% Created : 19 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||||
%%%
|
%%%
|
||||||
%%%
|
%%%
|
||||||
|
@ -36,6 +36,7 @@
|
||||||
adhoc_local_items/4, adhoc_local_commands/4,
|
adhoc_local_items/4, adhoc_local_commands/4,
|
||||||
get_sm_identity/5, get_sm_features/5, get_sm_items/5,
|
get_sm_identity/5, get_sm_features/5, get_sm_items/5,
|
||||||
adhoc_sm_items/4, adhoc_sm_commands/4, mod_options/1,
|
adhoc_sm_items/4, adhoc_sm_commands/4, mod_options/1,
|
||||||
|
mod_opt_type/1,
|
||||||
depends/2, mod_doc/0]).
|
depends/2, mod_doc/0]).
|
||||||
|
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
@ -92,6 +93,10 @@ depends(_Host, _Opts) ->
|
||||||
-spec tokenize(binary()) -> [binary()].
|
-spec tokenize(binary()) -> [binary()].
|
||||||
tokenize(Node) -> str:tokens(Node, <<"/#">>).
|
tokenize(Node) -> str:tokens(Node, <<"/#">>).
|
||||||
|
|
||||||
|
acl_match_rule(Host, From) ->
|
||||||
|
Access = mod_configure_opt:access(Host),
|
||||||
|
acl:match_rule(Host, Access, From).
|
||||||
|
|
||||||
-spec get_sm_identity([identity()], jid(), jid(), binary(), binary()) -> [identity()].
|
-spec get_sm_identity([identity()], jid(), jid(), binary(), binary()) -> [identity()].
|
||||||
get_sm_identity(Acc, _From, _To, Node, Lang) ->
|
get_sm_identity(Acc, _From, _To, Node, Lang) ->
|
||||||
case Node of
|
case Node of
|
||||||
|
@ -167,7 +172,7 @@ get_sm_features(Acc, From,
|
||||||
case gen_mod:is_loaded(LServer, mod_adhoc) of
|
case gen_mod:is_loaded(LServer, mod_adhoc) of
|
||||||
false -> Acc;
|
false -> Acc;
|
||||||
_ ->
|
_ ->
|
||||||
Allow = acl:match_rule(LServer, configure, From),
|
Allow = acl_match_rule(LServer, From),
|
||||||
case Node of
|
case Node of
|
||||||
<<"config">> -> ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang);
|
<<"config">> -> ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang);
|
||||||
_ -> Acc
|
_ -> Acc
|
||||||
|
@ -182,7 +187,7 @@ get_local_features(Acc, From,
|
||||||
false -> Acc;
|
false -> Acc;
|
||||||
_ ->
|
_ ->
|
||||||
LNode = tokenize(Node),
|
LNode = tokenize(Node),
|
||||||
Allow = acl:match_rule(LServer, configure, From),
|
Allow = acl_match_rule(LServer, From),
|
||||||
case LNode of
|
case LNode of
|
||||||
[<<"config">>] -> ?INFO_RESULT(Allow, [], Lang);
|
[<<"config">>] -> ?INFO_RESULT(Allow, [], Lang);
|
||||||
[<<"user">>] -> ?INFO_RESULT(Allow, [], Lang);
|
[<<"user">>] -> ?INFO_RESULT(Allow, [], Lang);
|
||||||
|
@ -240,7 +245,7 @@ get_local_features(Acc, From,
|
||||||
jid(), jid(), binary()) -> mod_disco:items_acc().
|
jid(), jid(), binary()) -> mod_disco:items_acc().
|
||||||
adhoc_sm_items(Acc, From, #jid{lserver = LServer} = To,
|
adhoc_sm_items(Acc, From, #jid{lserver = LServer} = To,
|
||||||
Lang) ->
|
Lang) ->
|
||||||
case acl:match_rule(LServer, configure, From) of
|
case acl_match_rule(LServer, From) of
|
||||||
allow ->
|
allow ->
|
||||||
Items = case Acc of
|
Items = case Acc of
|
||||||
{result, Its} -> Its;
|
{result, Its} -> Its;
|
||||||
|
@ -266,7 +271,7 @@ get_sm_items(Acc, From,
|
||||||
{result, Its} -> Its;
|
{result, Its} -> Its;
|
||||||
empty -> []
|
empty -> []
|
||||||
end,
|
end,
|
||||||
case {acl:match_rule(LServer, configure, From), Node} of
|
case {acl_match_rule(LServer, From), Node} of
|
||||||
{allow, <<"">>} ->
|
{allow, <<"">>} ->
|
||||||
Nodes = [?NODEJID(To, ?T("Configuration"),
|
Nodes = [?NODEJID(To, ?T("Configuration"),
|
||||||
<<"config">>),
|
<<"config">>),
|
||||||
|
@ -295,13 +300,13 @@ get_user_resources(User, Server) ->
|
||||||
jid(), jid(), binary()) -> mod_disco:items_acc().
|
jid(), jid(), binary()) -> mod_disco:items_acc().
|
||||||
adhoc_local_items(Acc, From,
|
adhoc_local_items(Acc, From,
|
||||||
#jid{lserver = LServer, server = Server} = To, Lang) ->
|
#jid{lserver = LServer, server = Server} = To, Lang) ->
|
||||||
case acl:match_rule(LServer, configure, From) of
|
case acl_match_rule(LServer, From) of
|
||||||
allow ->
|
allow ->
|
||||||
Items = case Acc of
|
Items = case Acc of
|
||||||
{result, Its} -> Its;
|
{result, Its} -> Its;
|
||||||
empty -> []
|
empty -> []
|
||||||
end,
|
end,
|
||||||
PermLev = get_permission_level(From),
|
PermLev = get_permission_level(From, LServer),
|
||||||
Nodes = recursively_get_local_items(PermLev, LServer,
|
Nodes = recursively_get_local_items(PermLev, LServer,
|
||||||
<<"">>, Server, Lang),
|
<<"">>, Server, Lang),
|
||||||
Nodes1 = lists:filter(
|
Nodes1 = lists:filter(
|
||||||
|
@ -348,9 +353,10 @@ recursively_get_local_items(PermLev, LServer, Node,
|
||||||
end,
|
end,
|
||||||
Items)).
|
Items)).
|
||||||
|
|
||||||
-spec get_permission_level(jid()) -> global | vhost.
|
-spec get_permission_level(jid(), binary()) -> global | vhost.
|
||||||
get_permission_level(JID) ->
|
get_permission_level(JID, Host) ->
|
||||||
case acl:match_rule(global, configure, JID) of
|
Access = mod_configure_opt:access(Host),
|
||||||
|
case acl:match_rule(global, Access, JID) of
|
||||||
allow -> global;
|
allow -> global;
|
||||||
deny -> vhost
|
deny -> vhost
|
||||||
end.
|
end.
|
||||||
|
@ -361,7 +367,7 @@ get_permission_level(JID) ->
|
||||||
case Allow of
|
case Allow of
|
||||||
deny -> Fallback;
|
deny -> Fallback;
|
||||||
allow ->
|
allow ->
|
||||||
PermLev = get_permission_level(From),
|
PermLev = get_permission_level(From, LServer),
|
||||||
case get_local_items({PermLev, LServer}, LNode,
|
case get_local_items({PermLev, LServer}, LNode,
|
||||||
jid:encode(To), Lang)
|
jid:encode(To), Lang)
|
||||||
of
|
of
|
||||||
|
@ -381,11 +387,11 @@ get_local_items(Acc, From, #jid{lserver = LServer} = To,
|
||||||
{result, Its} -> Its;
|
{result, Its} -> Its;
|
||||||
empty -> []
|
empty -> []
|
||||||
end,
|
end,
|
||||||
Allow = acl:match_rule(LServer, configure, From),
|
Allow = acl_match_rule(LServer, From),
|
||||||
case Allow of
|
case Allow of
|
||||||
deny -> {result, Items};
|
deny -> {result, Items};
|
||||||
allow ->
|
allow ->
|
||||||
PermLev = get_permission_level(From),
|
PermLev = get_permission_level(From, LServer),
|
||||||
case get_local_items({PermLev, LServer}, [],
|
case get_local_items({PermLev, LServer}, [],
|
||||||
jid:encode(To), Lang)
|
jid:encode(To), Lang)
|
||||||
of
|
of
|
||||||
|
@ -400,7 +406,7 @@ get_local_items(Acc, From, #jid{lserver = LServer} = To,
|
||||||
false -> Acc;
|
false -> Acc;
|
||||||
_ ->
|
_ ->
|
||||||
LNode = tokenize(Node),
|
LNode = tokenize(Node),
|
||||||
Allow = acl:match_rule(LServer, configure, From),
|
Allow = acl_match_rule(LServer, From),
|
||||||
Err = xmpp:err_forbidden(?T("Access denied by service policy"), Lang),
|
Err = xmpp:err_forbidden(?T("Access denied by service policy"), Lang),
|
||||||
case LNode of
|
case LNode of
|
||||||
[<<"config">>] ->
|
[<<"config">>] ->
|
||||||
|
@ -690,7 +696,7 @@ get_stopped_nodes(_Lang) ->
|
||||||
|
|
||||||
-define(COMMANDS_RESULT(LServerOrGlobal, From, To,
|
-define(COMMANDS_RESULT(LServerOrGlobal, From, To,
|
||||||
Request, Lang),
|
Request, Lang),
|
||||||
case acl:match_rule(LServerOrGlobal, configure, From) of
|
case acl_match_rule(LServerOrGlobal, From) of
|
||||||
deny -> {error, xmpp:err_forbidden(?T("Access denied by service policy"), Lang)};
|
deny -> {error, xmpp:err_forbidden(?T("Access denied by service policy"), Lang)};
|
||||||
allow -> adhoc_local_commands(From, To, Request)
|
allow -> adhoc_local_commands(From, To, Request)
|
||||||
end).
|
end).
|
||||||
|
@ -1268,7 +1274,7 @@ set_form(From, Host, ?NS_ADMINL(<<"add-user">>), _Lang,
|
||||||
Server = AccountJID#jid.lserver,
|
Server = AccountJID#jid.lserver,
|
||||||
true = lists:member(Server, ejabberd_option:hosts()),
|
true = lists:member(Server, ejabberd_option:hosts()),
|
||||||
true = Server == Host orelse
|
true = Server == Host orelse
|
||||||
get_permission_level(From) == global,
|
get_permission_level(From, Host) == global,
|
||||||
case ejabberd_auth:try_register(User, Server, Password) of
|
case ejabberd_auth:try_register(User, Server, Password) of
|
||||||
ok -> {result, undefined};
|
ok -> {result, undefined};
|
||||||
{error, exists} -> {error, xmpp:err_conflict()};
|
{error, exists} -> {error, xmpp:err_conflict()};
|
||||||
|
@ -1284,7 +1290,7 @@ set_form(From, Host, ?NS_ADMINL(<<"delete-user">>),
|
||||||
User = JID#jid.luser,
|
User = JID#jid.luser,
|
||||||
Server = JID#jid.lserver,
|
Server = JID#jid.lserver,
|
||||||
true = Server == Host orelse
|
true = Server == Host orelse
|
||||||
get_permission_level(From) == global,
|
get_permission_level(From, Host) == global,
|
||||||
true = ejabberd_auth:user_exists(User, Server),
|
true = ejabberd_auth:user_exists(User, Server),
|
||||||
{User, Server}
|
{User, Server}
|
||||||
end,
|
end,
|
||||||
|
@ -1298,7 +1304,7 @@ set_form(From, Host, ?NS_ADMINL(<<"end-user-session">>),
|
||||||
JID = jid:decode(AccountString),
|
JID = jid:decode(AccountString),
|
||||||
LServer = JID#jid.lserver,
|
LServer = JID#jid.lserver,
|
||||||
true = LServer == Host orelse
|
true = LServer == Host orelse
|
||||||
get_permission_level(From) == global,
|
get_permission_level(From, Host) == global,
|
||||||
case JID#jid.lresource of
|
case JID#jid.lresource of
|
||||||
<<>> ->
|
<<>> ->
|
||||||
ejabberd_sm:kick_user(JID#jid.luser, JID#jid.lserver);
|
ejabberd_sm:kick_user(JID#jid.luser, JID#jid.lserver);
|
||||||
|
@ -1314,7 +1320,7 @@ set_form(From, Host,
|
||||||
User = JID#jid.luser,
|
User = JID#jid.luser,
|
||||||
Server = JID#jid.lserver,
|
Server = JID#jid.lserver,
|
||||||
true = Server == Host orelse
|
true = Server == Host orelse
|
||||||
get_permission_level(From) == global,
|
get_permission_level(From, Host) == global,
|
||||||
true = ejabberd_auth:user_exists(User, Server),
|
true = ejabberd_auth:user_exists(User, Server),
|
||||||
ejabberd_auth:set_password(User, Server, Password),
|
ejabberd_auth:set_password(User, Server, Password),
|
||||||
{result, undefined};
|
{result, undefined};
|
||||||
|
@ -1325,7 +1331,7 @@ set_form(From, Host,
|
||||||
User = JID#jid.luser,
|
User = JID#jid.luser,
|
||||||
Server = JID#jid.lserver,
|
Server = JID#jid.lserver,
|
||||||
true = Server == Host orelse
|
true = Server == Host orelse
|
||||||
get_permission_level(From) == global,
|
get_permission_level(From, Host) == global,
|
||||||
FLast = case ejabberd_sm:get_user_resources(User,
|
FLast = case ejabberd_sm:get_user_resources(User,
|
||||||
Server)
|
Server)
|
||||||
of
|
of
|
||||||
|
@ -1357,7 +1363,7 @@ set_form(From, Host, ?NS_ADMINL(<<"user-stats">>), Lang,
|
||||||
User = JID#jid.luser,
|
User = JID#jid.luser,
|
||||||
Server = JID#jid.lserver,
|
Server = JID#jid.lserver,
|
||||||
true = Server == Host orelse
|
true = Server == Host orelse
|
||||||
get_permission_level(From) == global,
|
get_permission_level(From, Host) == global,
|
||||||
Resources = ejabberd_sm:get_user_resources(User,
|
Resources = ejabberd_sm:get_user_resources(User,
|
||||||
Server),
|
Server),
|
||||||
IPs1 = [ejabberd_sm:get_user_ip(User, Server, Resource)
|
IPs1 = [ejabberd_sm:get_user_ip(User, Server, Resource)
|
||||||
|
@ -1448,7 +1454,7 @@ adhoc_sm_commands(_Acc, From,
|
||||||
#jid{user = User, server = Server, lserver = LServer},
|
#jid{user = User, server = Server, lserver = LServer},
|
||||||
#adhoc_command{lang = Lang, node = <<"config">>,
|
#adhoc_command{lang = Lang, node = <<"config">>,
|
||||||
action = Action, xdata = XData} = Request) ->
|
action = Action, xdata = XData} = Request) ->
|
||||||
case acl:match_rule(LServer, configure, From) of
|
case acl_match_rule(LServer, From) of
|
||||||
deny ->
|
deny ->
|
||||||
{error, xmpp:err_forbidden(?T("Access denied by service policy"), Lang)};
|
{error, xmpp:err_forbidden(?T("Access denied by service policy"), Lang)};
|
||||||
allow ->
|
allow ->
|
||||||
|
@ -1530,12 +1536,41 @@ set_sm_form(_User, _Server, _Node, _Request) ->
|
||||||
tr(Lang, Text) ->
|
tr(Lang, Text) ->
|
||||||
translate:translate(Lang, Text).
|
translate:translate(Lang, Text).
|
||||||
|
|
||||||
mod_options(_) -> [].
|
-spec mod_opt_type(atom()) -> econf:validator().
|
||||||
|
mod_opt_type(access) ->
|
||||||
|
econf:acl().
|
||||||
|
|
||||||
|
-spec mod_options(binary()) -> [{services, [tuple()]} | {atom(), any()}].
|
||||||
|
mod_options(_Host) ->
|
||||||
|
[{access, configure}].
|
||||||
|
|
||||||
|
%% @format-begin
|
||||||
|
|
||||||
mod_doc() ->
|
mod_doc() ->
|
||||||
#{desc =>
|
#{desc =>
|
||||||
?T("The module provides server configuration functionality via "
|
?T("The module provides server configuration functionality via "
|
||||||
"https://xmpp.org/extensions/xep-0050.html[XEP-0050: Ad-Hoc Commands]. "
|
"https://xmpp.org/extensions/xep-0050.html[XEP-0050: Ad-Hoc Commands]. "
|
||||||
"Implements many commands as defined in "
|
"It also implements many commands as defined in "
|
||||||
"https://xmpp.org/extensions/xep-0133.html[XEP-0133: Service Administration]. "
|
"https://xmpp.org/extensions/xep-0133.html[XEP-0133: Service Administration]. "
|
||||||
"This module requires _`mod_adhoc`_ to be loaded.")}.
|
"This module requires _`mod_adhoc`_ (to execute the commands), "
|
||||||
|
"and recommends _`mod_disco`_ (to discover the commands). "),
|
||||||
|
opts =>
|
||||||
|
[{access,
|
||||||
|
#{value => ?T("AccessName"),
|
||||||
|
note => "added in 25.xx",
|
||||||
|
desc =>
|
||||||
|
?T("This option defines which access rule will be used to "
|
||||||
|
"control who is allowed to access the features provided by this module. "
|
||||||
|
"The default value is 'configure'.")}}],
|
||||||
|
example =>
|
||||||
|
["acl:",
|
||||||
|
" admin:",
|
||||||
|
" user: sun@localhost",
|
||||||
|
"",
|
||||||
|
"access_rules:",
|
||||||
|
" configure:",
|
||||||
|
" allow: admin",
|
||||||
|
"",
|
||||||
|
"modules:",
|
||||||
|
" mod_configure:",
|
||||||
|
" access: configure"]}.
|
||||||
|
|
13
src/mod_configure_opt.erl
Normal file
13
src/mod_configure_opt.erl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
%% Generated automatically
|
||||||
|
%% DO NOT EDIT: run `make options` instead
|
||||||
|
|
||||||
|
-module(mod_configure_opt).
|
||||||
|
|
||||||
|
-export([access/1]).
|
||||||
|
|
||||||
|
-spec access(gen_mod:opts() | global | binary()) -> 'configure' | acl:acl().
|
||||||
|
access(Opts) when is_map(Opts) ->
|
||||||
|
gen_mod:get_opt(access, Opts);
|
||||||
|
access(Host) ->
|
||||||
|
gen_mod:get_module_opt(Host, mod_configure, access).
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue