From 72572d990aa2bb53b8c2027d930ff4cc555b959e Mon Sep 17 00:00:00 2001 From: Evgeny Khramtsov Date: Fri, 21 Jun 2019 15:37:51 +0300 Subject: [PATCH] Allow multiple definitions of host_config and append_host_config --- src/ejabberd_config.erl | 41 ++++++++++++++++++++++++++++++++-------- src/ejabberd_options.erl | 6 ++++-- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 3bfcf65d2..1a6026fbf 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -492,15 +492,9 @@ read_erlang_file(File, _) -> Err end. --spec validate(term()) -> {ok, term()} | error_return(). +-spec validate(term()) -> {ok, [{atom(), term()}]} | error_return(). validate(Y1) -> - case econf:validate( - econf:options( - #{hosts => ejabberd_options:opt_type(hosts), - loglevel => ejabberd_options:opt_type(loglevel), - '_' => econf:any()}, - [{required, [hosts]}, unique]), - Y1) of + case pre_validate(Y1) of {ok, Y2} -> set_loglevel(proplists:get_value(loglevel, Y2, 4)), case ejabberd_config_transformer:map_reduce(Y2) of @@ -522,6 +516,23 @@ validate(Y1) -> Err end. +-spec pre_validate(term()) -> {ok, [{atom(), term()}]} | error_return(). +pre_validate(Y1) -> + case econf:validate( + econf:options( + #{hosts => ejabberd_options:opt_type(hosts), + loglevel => ejabberd_options:opt_type(loglevel), + host_config => econf:map(econf:binary(), econf:any()), + append_host_config => econf:map(econf:binary(), econf:any()), + '_' => econf:any()}, + [{required, [hosts]}]), + Y1) of + {ok, Y2} -> + {ok, group_duplicated_options(Y2, [append_host_config, host_config])}; + Err -> + Err + end. + -spec load_file(file:filename_all()) -> ok | error_return(). load_file(File) -> try @@ -725,3 +736,17 @@ set_node_start(UnixTime) -> -spec set_loglevel(0..5) -> ok. set_loglevel(Level) -> ejabberd_logger:set(Level). + +-spec group_duplicated_options([{atom(), term()}], [atom()]) -> [{atom(), term()}]. +group_duplicated_options(Y1, Options) -> + {Y2, Y3} = lists:partition( + fun({Option, _}) -> + lists:member(Option, Options) + end, Y1), + lists:foldl( + fun(Option, Y4) -> + case lists:flatten(proplists:get_all_values(Option, Y2)) of + [] -> Y4; + Values -> [{Option, Values}|Y4] + end + end, Y3, Options). diff --git a/src/ejabberd_options.erl b/src/ejabberd_options.erl index e47ca6711..c76d89ae1 100644 --- a/src/ejabberd_options.erl +++ b/src/ejabberd_options.erl @@ -55,7 +55,8 @@ opt_type(append_host_config) -> econf:and_then( econf:domain(), econf:enum(ejabberd_option:hosts())), - validator()); + validator(), + [unique]); opt_type(auth_cache_life_time) -> econf:timeout(second, infinity); opt_type(auth_cache_missed) -> @@ -145,7 +146,8 @@ opt_type(host_config) -> econf:and_then( econf:domain(), econf:enum(ejabberd_option:hosts())), - validator()); + validator(), + [unique]); opt_type(hosts) -> econf:non_empty(econf:list(econf:domain(), [unique])); opt_type(include_config_file) ->