2019-06-14 11:33:26 +02:00
|
|
|
%%%----------------------------------------------------------------------
|
2024-01-22 16:40:01 +01:00
|
|
|
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
2019-06-14 11:33:26 +02:00
|
|
|
%%%
|
|
|
|
%%% This program is free software; you can redistribute it and/or
|
|
|
|
%%% modify it under the terms of the GNU General Public License as
|
|
|
|
%%% published by the Free Software Foundation; either version 2 of the
|
|
|
|
%%% License, or (at your option) any later version.
|
|
|
|
%%%
|
|
|
|
%%% This program is distributed in the hope that it will be useful,
|
|
|
|
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
%%% General Public License for more details.
|
|
|
|
%%%
|
|
|
|
%%% You should have received a copy of the GNU General Public License along
|
|
|
|
%%% with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
%%%
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
-module(ejabberd_config_transformer).
|
|
|
|
|
|
|
|
%% API
|
|
|
|
-export([map_reduce/1]).
|
|
|
|
|
|
|
|
-include("logger.hrl").
|
|
|
|
|
|
|
|
%%%===================================================================
|
|
|
|
%%% API
|
|
|
|
%%%===================================================================
|
|
|
|
map_reduce(Y) ->
|
2019-12-16 12:39:56 +01:00
|
|
|
F =
|
|
|
|
fun(Y1) ->
|
|
|
|
Y2 = (validator())(Y1),
|
|
|
|
Y3 = transform(Y2),
|
|
|
|
case application:get_env(ejabberd, custom_config_transformer) of
|
|
|
|
{ok, TransMod} when is_atom(TransMod) ->
|
|
|
|
TransMod:transform(Y3);
|
|
|
|
_ ->
|
2019-06-14 11:33:26 +02:00
|
|
|
Y3
|
2019-12-16 12:39:56 +01:00
|
|
|
end
|
|
|
|
end,
|
2019-06-14 11:33:26 +02:00
|
|
|
econf:validate(F, Y).
|
|
|
|
|
|
|
|
%%%===================================================================
|
|
|
|
%%% Transformer
|
|
|
|
%%%===================================================================
|
|
|
|
transform(Y) ->
|
|
|
|
{Y1, Acc1} = transform(global, Y, #{}),
|
|
|
|
{Y2, Acc2} = update(Y1, Acc1),
|
|
|
|
filter(global, Y2, Acc2).
|
|
|
|
|
|
|
|
transform(Host, Y, Acc) ->
|
|
|
|
filtermapfoldr(
|
|
|
|
fun({Opt, HostOpts}, Acc1) when (Opt == host_config orelse
|
|
|
|
Opt == append_host_config)
|
|
|
|
andalso Host == global ->
|
|
|
|
case filtermapfoldr(
|
|
|
|
fun({Host1, Opts}, Acc2) ->
|
|
|
|
case transform(Host1, Opts, Acc2) of
|
|
|
|
{[], Acc3} ->
|
|
|
|
{false, Acc3};
|
|
|
|
{Opts1, Acc3} ->
|
|
|
|
{{true, {Host1, Opts1}}, Acc3}
|
|
|
|
end
|
|
|
|
end, Acc1, HostOpts) of
|
|
|
|
{[], Acc4} ->
|
|
|
|
{false, Acc4};
|
|
|
|
{HostOpts1, Acc4} ->
|
|
|
|
{{true, {Opt, HostOpts1}}, Acc4}
|
|
|
|
end;
|
|
|
|
({Opt, Val}, Acc1) ->
|
|
|
|
transform(Host, Opt, Val, Acc1)
|
|
|
|
end, Acc, Y).
|
|
|
|
|
|
|
|
transform(Host, modules, ModOpts, Acc) ->
|
|
|
|
{ModOpts1, Acc2} =
|
|
|
|
lists:mapfoldr(
|
|
|
|
fun({Mod, Opts}, Acc1) ->
|
|
|
|
Opts1 = transform_module_options(Opts),
|
|
|
|
transform_module(Host, Mod, Opts1, Acc1)
|
|
|
|
end, Acc, ModOpts),
|
|
|
|
{{true, {modules, ModOpts1}}, Acc2};
|
|
|
|
transform(global, listen, Listeners, Acc) ->
|
|
|
|
{Listeners1, Acc2} =
|
|
|
|
lists:mapfoldr(
|
|
|
|
fun(Opts, Acc1) ->
|
|
|
|
transform_listener(Opts, Acc1)
|
|
|
|
end, Acc, Listeners),
|
|
|
|
{{true, {listen, Listeners1}}, Acc2};
|
|
|
|
transform(_Host, Opt, CertFile, Acc) when (Opt == domain_certfile) orelse
|
|
|
|
(Opt == c2s_certfile) orelse
|
|
|
|
(Opt == s2s_certfile) ->
|
2019-09-23 14:17:20 +02:00
|
|
|
?WARNING_MSG("Option '~ts' is deprecated and was automatically "
|
|
|
|
"appended to 'certfiles' option. ~ts",
|
2019-06-14 11:33:26 +02:00
|
|
|
[Opt, adjust_hint()]),
|
|
|
|
CertFiles = maps:get(certfiles, Acc, []),
|
|
|
|
Acc1 = maps:put(certfiles, CertFiles ++ [CertFile], Acc),
|
|
|
|
{false, Acc1};
|
|
|
|
transform(_Host, certfiles, CertFiles1, Acc) ->
|
|
|
|
CertFiles2 = maps:get(certfiles, Acc, []),
|
|
|
|
Acc1 = maps:put(certfiles, CertFiles1 ++ CertFiles2, Acc),
|
|
|
|
{true, Acc1};
|
2019-09-20 11:36:31 +02:00
|
|
|
transform(_Host, acme, ACME, Acc) ->
|
|
|
|
ACME1 = lists:map(
|
|
|
|
fun({ca_url, URL} = Opt) ->
|
2020-06-01 10:35:28 +02:00
|
|
|
case misc:uri_parse(URL) of
|
2022-05-06 10:14:50 +02:00
|
|
|
{ok, _, _, "acme-v01.api.letsencrypt.org", _, _, _} ->
|
2019-09-20 11:36:31 +02:00
|
|
|
NewURL = ejabberd_acme:default_directory_url(),
|
2019-09-23 14:17:20 +02:00
|
|
|
?WARNING_MSG("ACME directory URL ~ts defined in "
|
2019-09-20 11:36:31 +02:00
|
|
|
"option acme->ca_url is deprecated "
|
|
|
|
"and was automatically replaced "
|
2019-09-23 14:17:20 +02:00
|
|
|
"with ~ts. ~ts",
|
2019-09-20 11:36:31 +02:00
|
|
|
[URL, NewURL, adjust_hint()]),
|
|
|
|
{ca_url, NewURL};
|
|
|
|
_ ->
|
|
|
|
Opt
|
|
|
|
end;
|
|
|
|
(Opt) ->
|
|
|
|
Opt
|
|
|
|
end, ACME),
|
|
|
|
{{true, {acme, ACME1}}, Acc};
|
2019-06-14 11:33:26 +02:00
|
|
|
transform(Host, s2s_use_starttls, required_trusted, Acc) ->
|
|
|
|
?WARNING_MSG("The value 'required_trusted' of option "
|
|
|
|
"'s2s_use_starttls' is deprecated and was "
|
|
|
|
"automatically replaced with value 'required'. "
|
|
|
|
"The module 'mod_s2s_dialback' has also "
|
2019-09-23 14:17:20 +02:00
|
|
|
"been automatically removed from the configuration. ~ts",
|
2019-06-14 11:33:26 +02:00
|
|
|
[adjust_hint()]),
|
|
|
|
Hosts = maps:get(remove_s2s_dialback, Acc, []),
|
|
|
|
Acc1 = maps:put(remove_s2s_dialback, [Host|Hosts], Acc),
|
|
|
|
{{true, {s2s_use_starttls, required}}, Acc1};
|
|
|
|
transform(_Host, _Opt, _Val, Acc) ->
|
|
|
|
{true, Acc}.
|
|
|
|
|
|
|
|
update(Y, Acc) ->
|
|
|
|
set_certfiles(Y, Acc).
|
|
|
|
|
|
|
|
filter(Host, Y, Acc) ->
|
|
|
|
lists:filtermap(
|
|
|
|
fun({Opt, HostOpts}) when (Opt == host_config orelse
|
|
|
|
Opt == append_host_config)
|
|
|
|
andalso Host == global ->
|
|
|
|
HostOpts1 = lists:map(
|
|
|
|
fun({Host1, Opts1}) ->
|
|
|
|
{Host1, filter(Host1, Opts1, Acc)}
|
|
|
|
end, HostOpts),
|
|
|
|
{true, {Opt, HostOpts1}};
|
|
|
|
({Opt, Val}) ->
|
|
|
|
filter(Host, Opt, Val, Acc)
|
|
|
|
end, Y).
|
|
|
|
|
Replace lager with built-in new logging API
This change requires Erlang/OTP-21.0 or higher.
The commit also deprecates the following options:
- log_rotate_date
- log_rate_limit
Furthermore, these options have no effect. The logger now fully
relies on log_rotate_size, that cannot be 0 anymore.
The loglevel option now accepts levels in literal formats.
Those are: none, emergency, alert, critical, error, warning, notice, info, debug.
Old integer values (0-5) are still supported and automatically converted
into literal format.
2019-10-18 18:12:32 +02:00
|
|
|
filter(_Host, log_rotate_date, _, _) ->
|
|
|
|
warn_removed_option(log_rotate_date),
|
|
|
|
false;
|
|
|
|
filter(_Host, log_rate_limit, _, _) ->
|
|
|
|
warn_removed_option(log_rate_limit),
|
|
|
|
false;
|
2019-06-14 11:33:26 +02:00
|
|
|
filter(_Host, ca_path, _, _) ->
|
|
|
|
warn_removed_option(ca_path, ca_file),
|
|
|
|
false;
|
|
|
|
filter(_Host, iqdisc, _, _) ->
|
|
|
|
warn_removed_option(iqdisc),
|
|
|
|
false;
|
|
|
|
filter(_Host, access, _, _) ->
|
|
|
|
warn_removed_option(access, access_rules),
|
|
|
|
false;
|
|
|
|
filter(_Host, commands, _, _) ->
|
|
|
|
warn_removed_option(commands, api_permissions),
|
|
|
|
false;
|
|
|
|
filter(_Host, ejabberdctl_access_commands, _, _) ->
|
|
|
|
warn_removed_option(ejabberdctl_access_commands, api_permissions),
|
|
|
|
false;
|
|
|
|
filter(_Host, commands_admin_access, _, _) ->
|
|
|
|
warn_removed_option(commands_admin_access, api_permissions),
|
|
|
|
false;
|
|
|
|
filter(_Host, ldap_group_cache_size, _, _) ->
|
|
|
|
warn_removed_option(ldap_group_cache_size, cache_size),
|
|
|
|
false;
|
|
|
|
filter(_Host, ldap_user_cache_size, _, _) ->
|
|
|
|
warn_removed_option(ldap_user_cache_size, cache_size),
|
|
|
|
false;
|
|
|
|
filter(_Host, ldap_group_cache_validity, _, _) ->
|
|
|
|
warn_removed_option(ldap_group_cache_validity, cache_life_time),
|
|
|
|
false;
|
|
|
|
filter(_Host, ldap_user_cache_validity, _, _) ->
|
|
|
|
warn_removed_option(ldap_user_cache_validity, cache_life_time),
|
|
|
|
false;
|
|
|
|
filter(_Host, ldap_local_filter, _, _) ->
|
|
|
|
warn_removed_option(ldap_local_filter),
|
|
|
|
false;
|
|
|
|
filter(_Host, deref_aliases, Val, _) ->
|
|
|
|
warn_replaced_option(deref_aliases, ldap_deref_aliases),
|
|
|
|
{true, {ldap_deref_aliases, Val}};
|
|
|
|
filter(_Host, default_db, internal, _) ->
|
|
|
|
{true, {default_db, mnesia}};
|
|
|
|
filter(_Host, default_db, odbc, _) ->
|
|
|
|
{true, {default_db, sql}};
|
|
|
|
filter(_Host, auth_method, Ms, _) ->
|
|
|
|
Ms1 = lists:map(
|
|
|
|
fun(internal) -> mnesia;
|
|
|
|
(odbc) -> sql;
|
|
|
|
(M) -> M
|
|
|
|
end, Ms),
|
|
|
|
{true, {auth_method, Ms1}};
|
|
|
|
filter(_Host, default_ram_db, internal, _) ->
|
|
|
|
{true, {default_ram_db, mnesia}};
|
|
|
|
filter(_Host, default_ram_db, odbc, _) ->
|
|
|
|
{true, {default_ram_db, sql}};
|
|
|
|
filter(_Host, extauth_cache, _, _) ->
|
|
|
|
?WARNING_MSG("Option 'extauth_cache' is deprecated "
|
|
|
|
"and has no effect, use authentication "
|
|
|
|
"or global cache configuration options: "
|
|
|
|
"auth_use_cache, auth_cache_life_time, "
|
|
|
|
"use_cache, cache_life_time, and so on", []),
|
|
|
|
false;
|
|
|
|
filter(_Host, extauth_instances, Val, _) ->
|
|
|
|
warn_replaced_option(extauth_instances, extauth_pool_size),
|
|
|
|
{true, {extauth_pool_size, Val}};
|
|
|
|
filter(_Host, Opt, Val, _) when Opt == outgoing_s2s_timeout;
|
|
|
|
Opt == s2s_dns_timeout ->
|
|
|
|
warn_huge_timeout(Opt, Val),
|
|
|
|
true;
|
2019-06-14 15:06:04 +02:00
|
|
|
filter(_Host, captcha_host, _, _) ->
|
|
|
|
warn_deprecated_option(captcha_host, captcha_url),
|
|
|
|
true;
|
2019-06-26 09:40:30 +02:00
|
|
|
filter(_Host, route_subdomains, _, _) ->
|
|
|
|
warn_removed_option(route_subdomains, s2s_access),
|
|
|
|
false;
|
2019-06-14 13:47:46 +02:00
|
|
|
filter(Host, modules, ModOpts, State) ->
|
|
|
|
NoDialbackHosts = maps:get(remove_s2s_dialback, State, []),
|
|
|
|
ModOpts1 = lists:filter(
|
|
|
|
fun({mod_s2s_dialback, _}) ->
|
|
|
|
not lists:member(Host, NoDialbackHosts);
|
|
|
|
({mod_echo, _}) ->
|
|
|
|
warn_removed_module(mod_echo),
|
|
|
|
false;
|
|
|
|
(_) ->
|
|
|
|
true
|
|
|
|
end, ModOpts),
|
2019-06-14 11:33:26 +02:00
|
|
|
{true, {modules, ModOpts1}};
|
|
|
|
filter(_, _, _, _) ->
|
|
|
|
true.
|
|
|
|
|
|
|
|
%%%===================================================================
|
|
|
|
%%% Listener transformers
|
|
|
|
%%%===================================================================
|
|
|
|
transform_listener(Opts, Acc) ->
|
|
|
|
Opts1 = transform_request_handlers(Opts),
|
2020-05-19 21:42:41 +02:00
|
|
|
Opts2 = transform_turn_ip(Opts1),
|
|
|
|
Opts3 = remove_inet_options(Opts2),
|
|
|
|
collect_listener_certfiles(Opts3, Acc).
|
2019-06-14 11:33:26 +02:00
|
|
|
|
|
|
|
transform_request_handlers(Opts) ->
|
|
|
|
case lists:keyfind(module, 1, Opts) of
|
|
|
|
{_, ejabberd_http} ->
|
|
|
|
replace_request_handlers(Opts);
|
2019-06-24 16:20:29 +02:00
|
|
|
{_, ejabberd_xmlrpc} ->
|
|
|
|
remove_xmlrpc_access_commands(Opts);
|
2019-06-14 11:33:26 +02:00
|
|
|
_ ->
|
|
|
|
Opts
|
|
|
|
end.
|
|
|
|
|
2020-05-19 21:42:41 +02:00
|
|
|
transform_turn_ip(Opts) ->
|
|
|
|
case lists:keyfind(module, 1, Opts) of
|
|
|
|
{_, ejabberd_stun} ->
|
|
|
|
replace_turn_ip(Opts);
|
|
|
|
_ ->
|
|
|
|
Opts
|
|
|
|
end.
|
|
|
|
|
2019-06-14 11:33:26 +02:00
|
|
|
replace_request_handlers(Opts) ->
|
|
|
|
Handlers = proplists:get_value(request_handlers, Opts, []),
|
|
|
|
Handlers1 =
|
|
|
|
lists:foldl(
|
|
|
|
fun({captcha, true}, Acc) ->
|
|
|
|
Handler = {<<"/captcha">>, ejabberd_captcha},
|
|
|
|
warn_replaced_handler(captcha, Handler),
|
|
|
|
[Handler|Acc];
|
|
|
|
({register, true}, Acc) ->
|
|
|
|
Handler = {<<"/register">>, mod_register_web},
|
|
|
|
warn_replaced_handler(register, Handler),
|
|
|
|
[Handler|Acc];
|
|
|
|
({web_admin, true}, Acc) ->
|
|
|
|
Handler = {<<"/admin">>, ejabberd_web_admin},
|
|
|
|
warn_replaced_handler(web_admin, Handler),
|
|
|
|
[Handler|Acc];
|
|
|
|
({http_bind, true}, Acc) ->
|
|
|
|
Handler = {<<"/bosh">>, mod_bosh},
|
|
|
|
warn_replaced_handler(http_bind, Handler),
|
|
|
|
[Handler|Acc];
|
|
|
|
({xmlrpc, true}, Acc) ->
|
|
|
|
Handler = {<<"/">>, ejabberd_xmlrpc},
|
|
|
|
warn_replaced_handler(xmlrpc, Handler),
|
|
|
|
Acc ++ [Handler];
|
|
|
|
(_, Acc) ->
|
|
|
|
Acc
|
|
|
|
end, Handlers, Opts),
|
|
|
|
Handlers2 = lists:map(
|
|
|
|
fun({Path, mod_http_bind}) ->
|
|
|
|
warn_replaced_module(mod_http_bind, mod_bosh),
|
|
|
|
{Path, mod_bosh};
|
|
|
|
(PathMod) ->
|
|
|
|
PathMod
|
|
|
|
end, Handlers1),
|
2019-07-03 08:54:56 +02:00
|
|
|
Opts1 = lists:filtermap(
|
|
|
|
fun({captcha, _}) -> false;
|
|
|
|
({register, _}) -> false;
|
|
|
|
({web_admin, _}) -> false;
|
|
|
|
({http_bind, _}) -> false;
|
|
|
|
({xmlrpc, _}) -> false;
|
|
|
|
({http_poll, _}) ->
|
|
|
|
?WARNING_MSG("Listening option 'http_poll' is "
|
|
|
|
"ignored: HTTP Polling support was "
|
2019-09-23 14:17:20 +02:00
|
|
|
"removed in ejabberd 15.04. ~ts",
|
2019-07-03 08:54:56 +02:00
|
|
|
[adjust_hint()]),
|
|
|
|
false;
|
|
|
|
({request_handlers, _}) ->
|
|
|
|
false;
|
|
|
|
(_) -> true
|
|
|
|
end, Opts),
|
|
|
|
case Handlers2 of
|
|
|
|
[] -> Opts1;
|
|
|
|
_ -> [{request_handlers, Handlers2}|Opts1]
|
|
|
|
end.
|
2019-06-14 11:33:26 +02:00
|
|
|
|
2019-06-24 16:20:29 +02:00
|
|
|
remove_xmlrpc_access_commands(Opts) ->
|
|
|
|
lists:filter(
|
|
|
|
fun({access_commands, _}) ->
|
|
|
|
warn_removed_option(access_commands, api_permissions),
|
|
|
|
false;
|
|
|
|
(_) ->
|
|
|
|
true
|
|
|
|
end, Opts).
|
|
|
|
|
2020-05-19 21:42:41 +02:00
|
|
|
replace_turn_ip(Opts) ->
|
|
|
|
lists:filtermap(
|
|
|
|
fun({turn_ip, Val}) ->
|
2020-05-29 18:40:19 +02:00
|
|
|
warn_replaced_option(turn_ip, turn_ipv4_address),
|
|
|
|
{true, {turn_ipv4_address, Val}};
|
2020-05-19 21:42:41 +02:00
|
|
|
(_) ->
|
|
|
|
true
|
|
|
|
end, Opts).
|
|
|
|
|
2019-06-14 11:33:26 +02:00
|
|
|
remove_inet_options(Opts) ->
|
|
|
|
lists:filter(
|
|
|
|
fun({Opt, _}) when Opt == inet; Opt == inet6 ->
|
|
|
|
warn_removed_option(Opt, ip),
|
|
|
|
false;
|
|
|
|
(_) ->
|
|
|
|
true
|
|
|
|
end, Opts).
|
|
|
|
|
|
|
|
collect_listener_certfiles(Opts, Acc) ->
|
|
|
|
Mod = proplists:get_value(module, Opts),
|
|
|
|
if Mod == ejabberd_http;
|
|
|
|
Mod == ejabberd_c2s;
|
|
|
|
Mod == ejabberd_s2s_in ->
|
|
|
|
case lists:keyfind(certfile, 1, Opts) of
|
|
|
|
{_, CertFile} ->
|
2019-09-23 14:17:20 +02:00
|
|
|
?WARNING_MSG("Listening option 'certfile' of module ~ts "
|
2019-06-14 11:33:26 +02:00
|
|
|
"is deprecated and was automatically "
|
2019-09-23 14:17:20 +02:00
|
|
|
"appended to global 'certfiles' option. ~ts",
|
2019-06-14 11:33:26 +02:00
|
|
|
[Mod, adjust_hint()]),
|
|
|
|
CertFiles = maps:get(certfiles, Acc, []),
|
|
|
|
{proplists:delete(certfile, Opts),
|
|
|
|
maps:put(certfiles, [CertFile|CertFiles], Acc)};
|
|
|
|
false ->
|
|
|
|
{Opts, Acc}
|
|
|
|
end;
|
|
|
|
true ->
|
|
|
|
{Opts, Acc}
|
|
|
|
end.
|
|
|
|
|
|
|
|
%%%===================================================================
|
|
|
|
%%% Module transformers
|
|
|
|
%%% NOTE: transform_module_options/1 is called before transform_module/4
|
|
|
|
%%%===================================================================
|
|
|
|
transform_module_options(Opts) ->
|
|
|
|
lists:filtermap(
|
|
|
|
fun({Opt, internal}) when Opt == db_type;
|
|
|
|
Opt == ram_db_type ->
|
|
|
|
{true, {Opt, mnesia}};
|
|
|
|
({Opt, odbc}) when Opt == db_type;
|
|
|
|
Opt == ram_db_type ->
|
|
|
|
{true, {Opt, sql}};
|
|
|
|
({deref_aliases, Val}) ->
|
|
|
|
warn_replaced_option(deref_aliases, ldap_deref_aliases),
|
|
|
|
{true, {ldap_deref_aliases, Val}};
|
|
|
|
({ldap_group_cache_size, _}) ->
|
|
|
|
warn_removed_option(ldap_group_cache_size, cache_size),
|
|
|
|
false;
|
|
|
|
({ldap_user_cache_size, _}) ->
|
|
|
|
warn_removed_option(ldap_user_cache_size, cache_size),
|
|
|
|
false;
|
|
|
|
({ldap_group_cache_validity, _}) ->
|
|
|
|
warn_removed_option(ldap_group_cache_validity, cache_life_time),
|
|
|
|
false;
|
|
|
|
({ldap_user_cache_validity, _}) ->
|
|
|
|
warn_removed_option(ldap_user_cache_validity, cache_life_time),
|
|
|
|
false;
|
|
|
|
({iqdisc, _}) ->
|
|
|
|
warn_removed_option(iqdisc),
|
|
|
|
false;
|
|
|
|
(_) ->
|
|
|
|
true
|
|
|
|
end, Opts).
|
|
|
|
|
2019-06-17 12:42:58 +02:00
|
|
|
transform_module(Host, mod_http_bind, Opts, Acc) ->
|
2019-06-14 11:33:26 +02:00
|
|
|
warn_replaced_module(mod_http_bind, mod_bosh),
|
2019-06-17 12:42:58 +02:00
|
|
|
transform_module(Host, mod_bosh, Opts, Acc);
|
|
|
|
transform_module(Host, mod_vcard_xupdate_odbc, Opts, Acc) ->
|
2019-06-14 11:33:26 +02:00
|
|
|
warn_replaced_module(mod_vcard_xupdate_odbc, mod_vcard_xupdate),
|
2019-06-17 12:42:58 +02:00
|
|
|
transform_module(Host, mod_vcard_xupdate, Opts, Acc);
|
|
|
|
transform_module(Host, mod_vcard_ldap, Opts, Acc) ->
|
2019-06-14 11:33:26 +02:00
|
|
|
warn_replaced_module(mod_vcard_ldap, mod_vcard, ldap),
|
2019-06-17 12:42:58 +02:00
|
|
|
transform_module(Host, mod_vcard, [{db_type, ldap}|Opts], Acc);
|
|
|
|
transform_module(Host, M, Opts, Acc) when (M == mod_announce_odbc orelse
|
|
|
|
M == mod_blocking_odbc orelse
|
|
|
|
M == mod_caps_odbc orelse
|
|
|
|
M == mod_last_odbc orelse
|
|
|
|
M == mod_muc_odbc orelse
|
|
|
|
M == mod_offline_odbc orelse
|
|
|
|
M == mod_privacy_odbc orelse
|
|
|
|
M == mod_private_odbc orelse
|
|
|
|
M == mod_pubsub_odbc orelse
|
|
|
|
M == mod_roster_odbc orelse
|
|
|
|
M == mod_shared_roster_odbc orelse
|
|
|
|
M == mod_vcard_odbc) ->
|
2019-06-14 11:33:26 +02:00
|
|
|
M1 = strip_odbc_suffix(M),
|
|
|
|
warn_replaced_module(M, M1, sql),
|
2019-06-17 12:42:58 +02:00
|
|
|
transform_module(Host, M1, [{db_type, sql}|Opts], Acc);
|
2019-06-14 11:33:26 +02:00
|
|
|
transform_module(_Host, mod_blocking, Opts, Acc) ->
|
|
|
|
Opts1 = lists:filter(
|
|
|
|
fun({db_type, _}) ->
|
|
|
|
warn_removed_module_option(db_type, mod_blocking),
|
|
|
|
false;
|
|
|
|
(_) ->
|
|
|
|
true
|
|
|
|
end, Opts),
|
|
|
|
{{mod_blocking, Opts1}, Acc};
|
|
|
|
transform_module(_Host, mod_carboncopy, Opts, Acc) ->
|
|
|
|
Opts1 = lists:filter(
|
|
|
|
fun({Opt, _}) when Opt == ram_db_type;
|
|
|
|
Opt == use_cache;
|
|
|
|
Opt == cache_size;
|
|
|
|
Opt == cache_missed;
|
|
|
|
Opt == cache_life_time ->
|
|
|
|
warn_removed_module_option(Opt, mod_carboncopy),
|
|
|
|
false;
|
|
|
|
(_) ->
|
|
|
|
true
|
|
|
|
end, Opts),
|
|
|
|
{{mod_carboncopy, Opts1}, Acc};
|
|
|
|
transform_module(_Host, mod_http_api, Opts, Acc) ->
|
|
|
|
Opts1 = lists:filter(
|
|
|
|
fun({admin_ip_access, _}) ->
|
|
|
|
warn_removed_option(admin_ip_access, api_permissions),
|
|
|
|
false;
|
|
|
|
(_) ->
|
|
|
|
true
|
|
|
|
end, Opts),
|
|
|
|
{{mod_http_api, Opts1}, Acc};
|
2019-06-14 16:38:55 +02:00
|
|
|
transform_module(_Host, mod_http_upload, Opts, Acc) ->
|
|
|
|
Opts1 = lists:filter(
|
|
|
|
fun({service_url, _}) ->
|
|
|
|
warn_deprecated_option(service_url, external_secret),
|
|
|
|
true;
|
|
|
|
(_) ->
|
|
|
|
true
|
|
|
|
end, Opts),
|
|
|
|
{{mod_http_upload, Opts1}, Acc};
|
2019-06-17 12:42:58 +02:00
|
|
|
transform_module(_Host, mod_pubsub, Opts, Acc) ->
|
|
|
|
Opts1 = lists:map(
|
|
|
|
fun({plugins, Plugins}) ->
|
|
|
|
{plugins,
|
|
|
|
lists:filter(
|
|
|
|
fun(Plugin) ->
|
|
|
|
case lists:member(
|
|
|
|
Plugin,
|
|
|
|
[<<"buddy">>, <<"club">>, <<"dag">>,
|
|
|
|
<<"dispatch">>, <<"hometree">>, <<"mb">>,
|
|
|
|
<<"mix">>, <<"online">>, <<"private">>,
|
|
|
|
<<"public">>]) of
|
|
|
|
true ->
|
|
|
|
?WARNING_MSG(
|
2019-09-23 14:17:20 +02:00
|
|
|
"Plugin '~ts' of mod_pubsub is not "
|
2019-06-17 12:42:58 +02:00
|
|
|
"supported anymore and has been "
|
|
|
|
"automatically removed from 'plugins' "
|
2019-09-23 14:17:20 +02:00
|
|
|
"option. ~ts",
|
2019-06-17 12:42:58 +02:00
|
|
|
[Plugin, adjust_hint()]),
|
|
|
|
false;
|
|
|
|
false ->
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end, Plugins)};
|
|
|
|
(Opt) ->
|
|
|
|
Opt
|
|
|
|
end, Opts),
|
|
|
|
{{mod_pubsub, Opts1}, Acc};
|
2019-06-14 11:33:26 +02:00
|
|
|
transform_module(_Host, Mod, Opts, Acc) ->
|
|
|
|
{{Mod, Opts}, Acc}.
|
|
|
|
|
|
|
|
strip_odbc_suffix(M) ->
|
|
|
|
[_|T] = lists:reverse(string:tokens(atom_to_list(M), "_")),
|
|
|
|
list_to_atom(string:join(lists:reverse(T), "_")).
|
|
|
|
|
|
|
|
%%%===================================================================
|
|
|
|
%%% Aux
|
|
|
|
%%%===================================================================
|
|
|
|
filtermapfoldr(Fun, Init, List) ->
|
|
|
|
lists:foldr(
|
|
|
|
fun(X, {Ret, Acc}) ->
|
|
|
|
case Fun(X, Acc) of
|
|
|
|
{true, Acc1} -> {[X|Ret], Acc1};
|
|
|
|
{{true, X1}, Acc1} -> {[X1|Ret], Acc1};
|
|
|
|
{false, Acc1} -> {Ret, Acc1}
|
|
|
|
end
|
|
|
|
end, {[], Init}, List).
|
|
|
|
|
|
|
|
set_certfiles(Y, #{certfiles := CertFiles} = Acc) ->
|
|
|
|
{lists:keystore(certfiles, 1, Y, {certfiles, CertFiles}), Acc};
|
|
|
|
set_certfiles(Y, Acc) ->
|
|
|
|
{Y, Acc}.
|
|
|
|
|
|
|
|
%%%===================================================================
|
|
|
|
%%% Warnings
|
|
|
|
%%%===================================================================
|
|
|
|
warn_replaced_module(From, To) ->
|
2019-09-23 14:17:20 +02:00
|
|
|
?WARNING_MSG("Module ~ts is deprecated and was automatically "
|
|
|
|
"replaced by ~ts. ~ts",
|
2019-06-14 11:33:26 +02:00
|
|
|
[From, To, adjust_hint()]).
|
|
|
|
|
|
|
|
warn_replaced_module(From, To, Type) ->
|
2019-09-23 14:17:20 +02:00
|
|
|
?WARNING_MSG("Module ~ts is deprecated and was automatically "
|
|
|
|
"replaced by ~ts with db_type: ~ts. ~ts",
|
2019-06-14 11:33:26 +02:00
|
|
|
[From, To, Type, adjust_hint()]).
|
|
|
|
|
2019-06-14 13:47:46 +02:00
|
|
|
warn_removed_module(Mod) ->
|
2019-09-23 14:17:20 +02:00
|
|
|
?WARNING_MSG("Module ~ts is deprecated and was automatically "
|
|
|
|
"removed from the configuration. ~ts", [Mod, adjust_hint()]).
|
2019-06-14 13:47:46 +02:00
|
|
|
|
2019-06-14 11:33:26 +02:00
|
|
|
warn_replaced_handler(Opt, {Path, Module}) ->
|
2019-09-23 14:17:20 +02:00
|
|
|
?WARNING_MSG("Listening option '~ts' is deprecated "
|
2019-06-14 11:33:26 +02:00
|
|
|
"and was automatically replaced by "
|
2019-09-23 14:17:20 +02:00
|
|
|
"HTTP request handler: \"~ts\" -> ~ts. ~ts",
|
2019-06-14 11:33:26 +02:00
|
|
|
[Opt, Path, Module, adjust_hint()]).
|
|
|
|
|
2019-06-14 15:06:04 +02:00
|
|
|
warn_deprecated_option(OldOpt, NewOpt) ->
|
2019-09-23 14:17:20 +02:00
|
|
|
?WARNING_MSG("Option '~ts' is deprecated. Use option '~ts' instead.",
|
2019-06-14 15:06:04 +02:00
|
|
|
[OldOpt, NewOpt]).
|
|
|
|
|
2019-06-14 11:33:26 +02:00
|
|
|
warn_replaced_option(OldOpt, NewOpt) ->
|
2019-09-23 14:17:20 +02:00
|
|
|
?WARNING_MSG("Option '~ts' is deprecated and was automatically "
|
|
|
|
"replaced by '~ts'. ~ts",
|
2019-06-14 11:33:26 +02:00
|
|
|
[OldOpt, NewOpt, adjust_hint()]).
|
|
|
|
|
|
|
|
warn_removed_option(Opt) ->
|
2019-09-23 14:17:20 +02:00
|
|
|
?WARNING_MSG("Option '~ts' is deprecated and has no effect anymore. "
|
2019-06-14 11:33:26 +02:00
|
|
|
"Please remove it from the configuration.", [Opt]).
|
|
|
|
|
|
|
|
warn_removed_option(OldOpt, NewOpt) ->
|
2019-09-23 14:17:20 +02:00
|
|
|
?WARNING_MSG("Option '~ts' is deprecated and has no effect anymore. "
|
|
|
|
"Use option '~ts' instead.", [OldOpt, NewOpt]).
|
2019-06-14 11:33:26 +02:00
|
|
|
|
|
|
|
warn_removed_module_option(Opt, Mod) ->
|
2019-09-23 14:17:20 +02:00
|
|
|
?WARNING_MSG("Option '~ts' of module ~ts is deprecated "
|
|
|
|
"and has no effect anymore. ~ts",
|
2019-06-14 11:33:26 +02:00
|
|
|
[Opt, Mod, adjust_hint()]).
|
|
|
|
|
|
|
|
warn_huge_timeout(Opt, T) when is_integer(T), T >= 1000 ->
|
2019-09-23 14:17:20 +02:00
|
|
|
?WARNING_MSG("Value '~B' of option '~ts' is too big, "
|
2019-06-14 11:33:26 +02:00
|
|
|
"are you sure you have set seconds?",
|
|
|
|
[T, Opt]);
|
|
|
|
warn_huge_timeout(_, _) ->
|
|
|
|
ok.
|
|
|
|
|
|
|
|
adjust_hint() ->
|
2019-06-14 13:47:46 +02:00
|
|
|
"Please adjust your configuration file accordingly. "
|
|
|
|
"Hint: run `ejabberdctl dump-config` command to view current "
|
2019-06-14 11:33:26 +02:00
|
|
|
"configuration as it is seen by ejabberd.".
|
|
|
|
|
|
|
|
%%%===================================================================
|
|
|
|
%%% Very raw validator: just to make sure we get properly typed terms
|
|
|
|
%%% Expand it if you need to transform more options, but don't
|
|
|
|
%%% abuse complex types: simple and composite types are preferred
|
|
|
|
%%%===================================================================
|
|
|
|
validator() ->
|
|
|
|
Validators =
|
|
|
|
#{s2s_use_starttls => econf:atom(),
|
|
|
|
certfiles => econf:list(econf:any()),
|
|
|
|
c2s_certfile => econf:binary(),
|
|
|
|
s2s_certfile => econf:binary(),
|
|
|
|
domain_certfile => econf:binary(),
|
|
|
|
default_db => econf:atom(),
|
|
|
|
default_ram_db => econf:atom(),
|
|
|
|
auth_method => econf:list_or_single(econf:atom()),
|
2019-09-20 11:36:31 +02:00
|
|
|
acme => econf:options(
|
|
|
|
#{ca_url => econf:binary(),
|
|
|
|
'_' => econf:any()},
|
|
|
|
[unique]),
|
2019-06-14 11:33:26 +02:00
|
|
|
listen =>
|
|
|
|
econf:list(
|
|
|
|
econf:options(
|
|
|
|
#{captcha => econf:bool(),
|
|
|
|
register => econf:bool(),
|
|
|
|
web_admin => econf:bool(),
|
|
|
|
http_bind => econf:bool(),
|
|
|
|
http_poll => econf:bool(),
|
|
|
|
xmlrpc => econf:bool(),
|
|
|
|
module => econf:atom(),
|
|
|
|
certfile => econf:binary(),
|
|
|
|
request_handlers =>
|
|
|
|
econf:map(econf:binary(), econf:atom()),
|
|
|
|
'_' => econf:any()},
|
|
|
|
[])),
|
|
|
|
modules =>
|
|
|
|
econf:options(
|
|
|
|
#{'_' =>
|
|
|
|
econf:options(
|
|
|
|
#{db_type => econf:atom(),
|
2019-06-17 12:42:58 +02:00
|
|
|
plugins => econf:list(econf:binary()),
|
2019-06-14 11:33:26 +02:00
|
|
|
'_' => econf:any()},
|
|
|
|
[])},
|
|
|
|
[]),
|
|
|
|
'_' => econf:any()},
|
|
|
|
econf:options(
|
|
|
|
Validators#{host_config =>
|
|
|
|
econf:map(econf:binary(),
|
|
|
|
econf:options(Validators, [])),
|
|
|
|
append_host_config =>
|
|
|
|
econf:map(econf:binary(),
|
|
|
|
econf:options(Validators, []))},
|
|
|
|
[]).
|