Skip to content

Commit

Permalink
Merge pull request #3606 from esl/mod_register-map-config
Browse files Browse the repository at this point in the history
Put mod_register opts in maps with defaults
  • Loading branch information
arcusfelis authored Mar 23, 2022
2 parents bda07f6 + de7ead7 commit 25c7d77
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 59 deletions.
12 changes: 5 additions & 7 deletions big_tests/tests/accounts_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,9 @@ required_modules() ->
[{mod_register, mod_register_options()}].

mod_register_options() ->
[{welcome_message, {"", ""}},
{ip_access, [{allow, "127.0.0.0/8"},
{deny, "0.0.0.0/0"}]},
{access, register},
{registration_watchers, []}].
config_parser_helper:mod_config(mod_register, #{ip_access => [{allow, "127.0.0.0/8"},
{deny, "0.0.0.0/0"}],
access => register}).

init_per_group(bad_cancelation, Config) ->
escalus:create_users(Config, escalus:get_users([alice]));
Expand Down Expand Up @@ -140,7 +138,7 @@ init_per_testcase(admin_notify, Config) ->
escalus:init_per_testcase(admin_notify, Config);
init_per_testcase(not_allowed_registration_cancelation, Config) ->
%% Use a configuration that will not allow inband cancelation (and registration).
reload_mod_register_option(Config, access, {access, none}),
reload_mod_register_option(Config, access, none),
escalus:init_per_testcase(not_allowed_registration_cancelation, Config);
init_per_testcase(registration_failure_timeout, Config) ->
Config1 = deny_everyone_registration(Config),
Expand Down Expand Up @@ -433,7 +431,7 @@ user_exists(Name, Config) ->
reload_mod_register_option(Config, Key, Value) ->
Host = host_type(),
Args = proplists:get_value(mod_register_options, Config),
Args1 = lists:keyreplace(Key, 1, Args, {Key, Value}),
Args1 = maps:put(Key, Value, Args),
dynamic_modules:restart(Host, mod_register, Args1).

restore_mod_register_options(Config) ->
Expand Down
1 change: 1 addition & 0 deletions doc/modules/mod_register.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ List of JIDs, which should receive a `<message>` notification about every succes

Specifies minimal entropy of allowed password.
Entropy is measured with `ejabberd_auth:entropy/1`.
When set to `0`, the password strength is not checked.
Recommended minimum is 32.
The entropy calculation algorithm is described in a section below.

Expand Down
1 change: 0 additions & 1 deletion rel/files/mongooseim.toml
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,6 @@
{{{mod_private}}}
{{/mod_private}}
[modules.mod_register]
welcome_message = {body = "", subject = ""}
ip_access = [
{address = "127.0.0.0/8", policy = "allow"},
{address = "0.0.0.0/0", policy = "deny"}
Expand Down
45 changes: 24 additions & 21 deletions src/mod_register.erl
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,8 @@
-include("jlib.hrl").
-include("mongoose_config_spec.hrl").

-spec start(mongooseim:host_type(), list()) -> ok.
start(HostType, Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),

-spec start(mongooseim:host_type(), gen_mod:module_opts()) -> ok.
start(HostType, #{iqdisc := IQDisc}) ->
[gen_iq_handler:add_iq_handler_for_domain(HostType, ?NS_REGISTER, Component, Fn, #{}, IQDisc) ||
{Component, Fn} <- iq_handlers()],
ejabberd_hooks:add(hooks(HostType)),
Expand All @@ -78,7 +76,7 @@ iq_handlers() ->

hooks(HostType) ->
[{c2s_stream_features, HostType, ?MODULE, c2s_stream_features, 50},
{c2s_unauthenticated_iq, HostType, ?MODULE, unauthenticated_iq_register, 50}].
{c2s_unauthenticated_iq, HostType, ?MODULE, unauthenticated_iq_register, 50}].

%%%
%%% config_spec
Expand All @@ -96,13 +94,22 @@ config_spec() ->
<<"password_strength">> => #option{type = integer,
validate = non_negative},
<<"ip_access">> => #list{items = ip_access_spec()}
}
},
format_items = map,
defaults = #{<<"iqdisc">> => one_queue,
<<"access">> => all,
<<"registration_watchers">> => [],
<<"password_strength">> => 0,
<<"ip_access">> => []}
}.

welcome_message_spec() ->
#section{
items = #{<<"body">> => #option{type = string},
<<"subject">> => #option{type = string}},
defaults = #{<<"body">> => "",
<<"subject">> => ""},
format_items = map,
process = fun ?MODULE:process_welcome_message/1
}.

Expand All @@ -114,18 +121,16 @@ ip_access_spec() ->
validate = {enum, [allow, deny]}}
},
required = all,
format_items = map,
process = fun ?MODULE:process_ip_access/1
}.

supported_features() -> [dynamic_domains].

process_ip_access(KVs) ->
{[[{address, Address}], [{policy, Policy}]], []} = proplists:split(KVs, [address, policy]),
process_ip_access(#{policy := Policy, address := Address}) ->
{Policy, Address}.

process_welcome_message(KVs) ->
Body = proplists:get_value(body, KVs, ""),
Subject = proplists:get_value(subject, KVs, ""),
process_welcome_message(#{subject := Subject, body := Body}) ->
{Subject, Body}.

%%%
Expand Down Expand Up @@ -259,7 +264,7 @@ attempt_cancelation(HostType, #jid{} = ClientJID, #jid{lserver = ServerDomain},
inband_registration_and_cancelation_allowed(_HostType, _ServerDomain, no_JID) ->
true;
inband_registration_and_cancelation_allowed(HostType, ServerDomain, JID) ->
Rule = gen_mod:get_module_opt(HostType, ?MODULE, access, none),
Rule = gen_mod:get_module_opt(HostType, ?MODULE, access),
allow =:= acl:match_rule(HostType, ServerDomain, Rule, JID).

process_iq_get(_HostType, From, _To, #iq{lang = Lang, sub_el = Child} = IQ, _Source) ->
Expand Down Expand Up @@ -331,7 +336,7 @@ try_register(HostType, User, Server, Password, SourceRaw, Lang) ->
{error, mongoose_xmpp_errors:bad_request()};
_ ->
JID = jid:make(User, Server, <<>>),
Access = gen_mod:get_module_opt(HostType, ?MODULE, access, all),
Access = gen_mod:get_module_opt(HostType, ?MODULE, access),
IPAccess = get_ip_access(HostType),
case {acl:match_rule(HostType, Server, Access, JID),
check_ip_access(SourceRaw, IPAccess)} of
Expand Down Expand Up @@ -367,8 +372,8 @@ verify_password_and_register(HostType, #jid{} = JID, Password, SourceRaw, Lang)
end.

send_welcome_message(HostType, #jid{lserver = Server} = JID) ->
case gen_mod:get_module_opt(HostType, ?MODULE, welcome_message, {"", ""}) of
{"", ""} ->
case gen_mod:get_module_opt(HostType, ?MODULE, welcome_message, undefined) of
undefined ->
ok;
{Subj, Body} ->
ejabberd_router:route(
Expand All @@ -378,13 +383,11 @@ send_welcome_message(HostType, #jid{lserver = Server} = JID) ->
children = [#xmlel{name = <<"subject">>,
children = [#xmlcdata{content = Subj}]},
#xmlel{name = <<"body">>,
children = [#xmlcdata{content = Body}]}]});
_ ->
ok
children = [#xmlcdata{content = Body}]}]})
end.

send_registration_notifications(HostType, #jid{lserver = Domain} = UJID, Source) ->
case gen_mod:get_module_opt(HostType, ?MODULE, registration_watchers, []) of
case gen_mod:get_module_opt(HostType, ?MODULE, registration_watchers) of
[] -> ok;
JIDs when is_list(JIDs) ->
Body = lists:flatten(
Expand Down Expand Up @@ -472,7 +475,7 @@ write_time({{Y, Mo, D}, {H, Mi, S}}) ->
[Y, Mo, D, H, Mi, S]).

is_strong_password(HostType, Password) ->
case gen_mod:get_module_opt(HostType, ?MODULE, password_strength, 0) of
case gen_mod:get_module_opt(HostType, ?MODULE, password_strength) of
Entropy when is_number(Entropy), Entropy == 0 ->
true;
Entropy when is_number(Entropy), Entropy > 0 ->
Expand All @@ -488,7 +491,7 @@ is_strong_password(HostType, Password) ->
%%%

get_ip_access(HostType) ->
IPAccess = gen_mod:get_module_opt(HostType, ?MODULE, ip_access, []),
IPAccess = gen_mod:get_module_opt(HostType, ?MODULE, ip_access),
lists:flatmap(
fun({Access, {IP, Mask}}) ->
[{Access, IP, Mask}];
Expand Down
18 changes: 10 additions & 8 deletions test/common/config_parser_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -614,11 +614,10 @@ all_modules() ->
full_text_search => false,
same_mam_id_for_peers => false,
user_prefs_store => rdbms}}),
mod_register =>
[{access, all},
{password_strength, 32},
{registration_watchers, [<<"JID1">>, <<"JID2">>]},
{welcome_message, {"Subject", "Body"}}],
mod_register => mod_config(mod_register, #{access => all,
password_strength => 32,
registration_watchers => [<<"JID1">>, <<"JID2">>],
welcome_message => {"Subject", "Body"}}),
mod_mam_rdbms_arch =>
mod_config(mod_mam_rdbms_arch, #{no_writer => true}),
mod_event_pusher_rabbit =>
Expand Down Expand Up @@ -684,9 +683,9 @@ pgsql_modules() ->
mod_privacy => mod_config(mod_privacy, #{backend => rdbms}),
mod_private => default_mod_config(mod_private),
mod_register =>
[{access, register},
{ip_access, [{allow, "127.0.0.0/8"}, {deny, "0.0.0.0/0"}]},
{welcome_message, {"Hello", "I am MongooseIM"}}],
mod_config(mod_register, #{access => register,
ip_access => [{allow, "127.0.0.0/8"}, {deny, "0.0.0.0/0"}],
welcome_message => {"Hello", "I am MongooseIM"}}),
mod_roster => mod_config(mod_roster, #{backend => rdbms}),
mod_sic => default_mod_config(mod_sic),
mod_stream_management => default_mod_config(mod_stream_management),
Expand Down Expand Up @@ -965,6 +964,9 @@ default_mod_config(mod_pubsub) ->
default_node_config => [], item_publisher => false, sync_broadcast => false};
default_mod_config(mod_push_service_mongoosepush) ->
#{pool_name => undefined, api_version => <<"v3">>, max_http_connections => 100};
default_mod_config(mod_register) ->
#{iqdisc => one_queue, access => all, registration_watchers => [],
password_strength => 0, ip_access => []};
default_mod_config(mod_roster) ->
#{iqdisc => one_queue, versioning => false, store_current_id => false, backend => mnesia};
default_mod_config(mod_shared_roster_ldap) ->
Expand Down
39 changes: 17 additions & 22 deletions test/config_parser_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2715,46 +2715,41 @@ mod_push_service_mongoosepush(_Config) ->
?errh(T(#{<<"max_http_connections">> => -1})).

mod_register(_Config) ->
?cfgh(modopts(mod_register, [{access,register},
{ip_access, [{allow,"127.0.0.0/8"},
{deny,"0.0.0.0"}]}
]),
check_module_defaults(mod_register),
check_iqdisc_map(mod_register),
P = [modules, mod_register],
?cfgh(P ++ [access], register,
ip_access_register(<<"127.0.0.1">>)),
?cfgh(P ++ [ip_access], [{allow, "127.0.0.0/8"},
{deny, "0.0.0.0"}],
ip_access_register(<<"0.0.0.0">>)),
?cfgh(modopts(mod_register, [{access,register},
{ip_access, [{allow,"127.0.0.0/8"},
{deny,"0.0.0.4"}]}
]),
?cfgh(P ++ [ip_access], [{allow, "127.0.0.0/8"},
{deny, "0.0.0.4"}],
ip_access_register(<<"0.0.0.4">>)),
?cfgh(modopts(mod_register, [{access,register},
{ip_access, [{allow,"127.0.0.0/8"},
{deny,"::1"}]}
]),
?cfgh(P ++ [ip_access], [{allow, "127.0.0.0/8"},
{deny, "::1"}],
ip_access_register(<<"::1">>)),
?cfgh(modopts(mod_register, [{access,register},
{ip_access, [{allow,"127.0.0.0/8"},
{deny,"::1/128"}]}
]),
?cfgh(P ++ [ip_access], [{allow, "127.0.0.0/8"},
{deny, "::1/128"}],
ip_access_register(<<"::1/128">>)),
?errh(invalid_ip_access_register()),
?errh(invalid_ip_access_register_ipv6()),
?errh(ip_access_register(<<"hello">>)),
?errh(ip_access_register(<<"0.d">>)),
?cfgh(modopts(mod_register, [{welcome_message, {"Subject", "Body"}}]),
?cfgh(P ++ [welcome_message], {"Subject", "Body"},
welcome_message()),
%% List of jids
?cfgh(modopts(mod_register, [{registration_watchers,
[<<"alice@bob">>, <<"ilovemongoose@help">>]}]),
?cfgh(P ++ [registration_watchers], [<<"alice@bob">>, <<"ilovemongoose@help">>],
registration_watchers([<<"alice@bob">>, <<"ilovemongoose@help">>])),
?errh(registration_watchers([<<"alice@bob">>, <<"jids@have@no@feelings!">>])),
%% non-negative integer
?cfgh(modopts(mod_register, [{password_strength, 42}]),
?cfgh(P ++ [password_strength], 42,
password_strength_register(42)),
?errh(password_strength_register(<<"42">>)),
?errh(password_strength_register(<<"strong">>)),
?errh(password_strength_register(-150)),
?errh(welcome_message(<<"Subject">>, 1)),
?errh(welcome_message(1, <<"Body">>)),
check_iqdisc(mod_register).
?errh(welcome_message(1, <<"Body">>)).

welcome_message() ->
welcome_message(<<"Subject">>, <<"Body">>).
Expand Down

0 comments on commit 25c7d77

Please sign in to comment.