2010-11-04 22:34:18 +01:00
|
|
|
%%%-------------------------------------------------------------------
|
|
|
|
%%% File : mod_register_web.erl
|
|
|
|
%%% Author : Badlop <badlop@process-one.net>
|
|
|
|
%%% Purpose : Web page to register account and related tasks
|
|
|
|
%%% Created : 4 May 2008 by Badlop <badlop@process-one.net>
|
|
|
|
%%%
|
|
|
|
%%%
|
2021-01-27 16:55:25 +01:00
|
|
|
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
|
2010-11-04 22:34:18 +01: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.
|
|
|
|
%%%
|
2014-02-22 11:27:40 +01:00
|
|
|
%%% 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.
|
2010-11-04 22:34:18 +01:00
|
|
|
%%%
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
|
|
|
-module(mod_register_web).
|
2013-03-14 10:33:02 +01:00
|
|
|
|
2010-11-04 22:34:18 +01:00
|
|
|
-author('badlop@process-one.net').
|
|
|
|
|
|
|
|
-behaviour(gen_mod).
|
|
|
|
|
2018-01-23 08:54:52 +01:00
|
|
|
-export([start/2, stop/1, reload/3, process/2, mod_options/1, depends/2]).
|
2020-01-08 10:24:51 +01:00
|
|
|
-export([mod_doc/0]).
|
2010-11-04 22:34:18 +01:00
|
|
|
|
2013-04-08 11:12:54 +02:00
|
|
|
-include("logger.hrl").
|
2013-03-14 10:33:02 +01:00
|
|
|
|
2020-09-03 13:45:57 +02:00
|
|
|
-include_lib("xmpp/include/xmpp.hrl").
|
2013-03-14 10:33:02 +01:00
|
|
|
|
2010-11-04 22:34:18 +01:00
|
|
|
-include("ejabberd_http.hrl").
|
2013-03-14 10:33:02 +01:00
|
|
|
|
2010-11-04 22:34:18 +01:00
|
|
|
-include("ejabberd_web_admin.hrl").
|
|
|
|
|
2019-06-22 16:08:45 +02:00
|
|
|
-include("translate.hrl").
|
|
|
|
|
2010-11-04 22:34:18 +01:00
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
%%% gen_mod callbacks
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
|
|
|
start(_Host, _Opts) ->
|
2019-06-14 11:33:26 +02:00
|
|
|
%% case mod_register_web_opt:docroot(Opts, fun(A) -> A end, undefined) of
|
2010-11-04 22:34:18 +01:00
|
|
|
ok.
|
|
|
|
|
2013-03-14 10:33:02 +01:00
|
|
|
stop(_Host) -> ok.
|
2010-11-04 22:34:18 +01:00
|
|
|
|
2017-02-22 17:46:47 +01:00
|
|
|
reload(_Host, _NewOpts, _OldOpts) ->
|
|
|
|
ok.
|
|
|
|
|
2016-07-06 13:58:48 +02:00
|
|
|
depends(_Host, _Opts) ->
|
|
|
|
[{mod_register, hard}].
|
|
|
|
|
2010-11-04 22:34:18 +01:00
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
%%% HTTP handlers
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
|
|
|
process([], #request{method = 'GET', lang = Lang}) ->
|
|
|
|
index_page(Lang);
|
2013-03-14 10:33:02 +01:00
|
|
|
process([<<"register.css">>],
|
|
|
|
#request{method = 'GET'}) ->
|
2010-11-04 22:34:18 +01:00
|
|
|
serve_css();
|
2020-02-26 13:27:22 +01:00
|
|
|
process([Section],
|
2013-03-14 10:33:02 +01:00
|
|
|
#request{method = 'GET', lang = Lang, host = Host,
|
2020-02-26 13:27:22 +01:00
|
|
|
ip = {Addr, _Port}}) ->
|
|
|
|
Host2 = case ejabberd_router:is_my_host(Host) of
|
2019-08-13 17:30:28 +02:00
|
|
|
true ->
|
2020-02-26 13:27:22 +01:00
|
|
|
Host;
|
2019-08-13 17:30:28 +02:00
|
|
|
false ->
|
2020-02-26 13:27:22 +01:00
|
|
|
<<"">>
|
|
|
|
end,
|
|
|
|
case Section of
|
|
|
|
<<"new">> -> form_new_get(Host2, Lang, Addr);
|
|
|
|
<<"delete">> -> form_del_get(Host2, Lang);
|
|
|
|
<<"change_password">> -> form_changepass_get(Host2, Lang);
|
|
|
|
_ -> {404, [], "Not Found"}
|
2019-08-13 17:30:28 +02:00
|
|
|
end;
|
2013-03-14 10:33:02 +01:00
|
|
|
process([<<"new">>],
|
|
|
|
#request{method = 'POST', q = Q, ip = {Ip, _Port},
|
2015-04-22 11:01:13 +02:00
|
|
|
lang = Lang, host = _HTTPHost}) ->
|
2021-10-04 11:24:24 +02:00
|
|
|
case form_new_post(Q, Ip) of
|
2013-03-14 10:33:02 +01:00
|
|
|
{success, ok, {Username, Host, _Password}} ->
|
2017-02-25 08:01:01 +01:00
|
|
|
Jid = jid:make(Username, Host),
|
2013-03-14 10:33:02 +01:00
|
|
|
mod_register:send_registration_notifications(?MODULE, Jid, Ip),
|
2021-01-22 14:21:57 +01:00
|
|
|
Text = translate:translate(Lang, ?T("Your XMPP account was successfully registered.")),
|
2013-03-14 10:33:02 +01:00
|
|
|
{200, [], Text};
|
|
|
|
Error ->
|
|
|
|
ErrorText =
|
2021-01-22 14:21:57 +01:00
|
|
|
list_to_binary([translate:translate(Lang, ?T("There was an error creating the account: ")),
|
2019-06-22 16:08:45 +02:00
|
|
|
translate:translate(Lang, get_error_text(Error))]),
|
2013-03-14 10:33:02 +01:00
|
|
|
{404, [], ErrorText}
|
2010-11-04 22:34:18 +01:00
|
|
|
end;
|
2013-03-14 10:33:02 +01:00
|
|
|
process([<<"delete">>],
|
|
|
|
#request{method = 'POST', q = Q, lang = Lang,
|
2016-02-04 21:31:16 +01:00
|
|
|
host = _HTTPHost}) ->
|
|
|
|
case form_del_post(Q) of
|
2013-03-14 10:33:02 +01:00
|
|
|
{atomic, ok} ->
|
2021-01-22 14:21:57 +01:00
|
|
|
Text = translate:translate(Lang, ?T("Your XMPP account was successfully unregistered.")),
|
2013-03-14 10:33:02 +01:00
|
|
|
{200, [], Text};
|
|
|
|
Error ->
|
|
|
|
ErrorText =
|
2021-01-22 14:21:57 +01:00
|
|
|
list_to_binary([translate:translate(Lang, ?T("There was an error deleting the account: ")),
|
2019-06-22 16:08:45 +02:00
|
|
|
translate:translate(Lang, get_error_text(Error))]),
|
2013-03-14 10:33:02 +01:00
|
|
|
{404, [], ErrorText}
|
2010-11-04 22:34:18 +01:00
|
|
|
end;
|
|
|
|
%% TODO: Currently only the first vhost is usable. The web request record
|
|
|
|
%% should include the host where the POST was sent.
|
2013-03-14 10:33:02 +01:00
|
|
|
process([<<"change_password">>],
|
|
|
|
#request{method = 'POST', q = Q, lang = Lang,
|
2016-02-04 21:31:16 +01:00
|
|
|
host = _HTTPHost}) ->
|
|
|
|
case form_changepass_post(Q) of
|
2013-03-14 10:33:02 +01:00
|
|
|
{atomic, ok} ->
|
2021-01-22 14:21:57 +01:00
|
|
|
Text = translate:translate(Lang, ?T("The password of your XMPP account was successfully changed.")),
|
2013-03-14 10:33:02 +01:00
|
|
|
{200, [], Text};
|
|
|
|
Error ->
|
|
|
|
ErrorText =
|
2021-01-22 14:21:57 +01:00
|
|
|
list_to_binary([translate:translate(Lang, ?T("There was an error changing the password: ")),
|
2019-06-22 16:08:45 +02:00
|
|
|
translate:translate(Lang, get_error_text(Error))]),
|
2013-03-14 10:33:02 +01:00
|
|
|
{404, [], ErrorText}
|
2014-04-30 06:39:17 +02:00
|
|
|
end;
|
|
|
|
|
2015-01-08 19:00:26 +01:00
|
|
|
process(_Path, _Request) ->
|
2014-04-30 06:39:17 +02:00
|
|
|
{404, [], "Not Found"}.
|
2010-11-04 22:34:18 +01:00
|
|
|
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
%%% CSS
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
|
|
|
serve_css() ->
|
2017-10-09 20:46:38 +02:00
|
|
|
case css() of
|
|
|
|
{ok, CSS} ->
|
|
|
|
{200,
|
|
|
|
[{<<"Content-Type">>, <<"text/css">>}, last_modified(),
|
|
|
|
cache_control_public()], CSS};
|
|
|
|
error ->
|
|
|
|
{404, [], "CSS not found"}
|
|
|
|
end.
|
2010-11-04 22:34:18 +01:00
|
|
|
|
|
|
|
last_modified() ->
|
2013-03-14 10:33:02 +01:00
|
|
|
{<<"Last-Modified">>,
|
|
|
|
<<"Mon, 25 Feb 2008 13:23:30 GMT">>}.
|
|
|
|
|
2010-11-04 22:34:18 +01:00
|
|
|
cache_control_public() ->
|
2013-03-14 10:33:02 +01:00
|
|
|
{<<"Cache-Control">>, <<"public">>}.
|
2010-11-04 22:34:18 +01:00
|
|
|
|
2017-10-09 20:46:38 +02:00
|
|
|
-spec css() -> {ok, binary()} | error.
|
2010-11-04 22:34:18 +01:00
|
|
|
css() ->
|
2017-10-09 20:46:38 +02:00
|
|
|
Dir = misc:css_dir(),
|
|
|
|
File = filename:join(Dir, "register.css"),
|
|
|
|
case file:read_file(File) of
|
|
|
|
{ok, Data} ->
|
|
|
|
{ok, Data};
|
|
|
|
{error, Why} ->
|
2021-01-22 14:21:57 +01:00
|
|
|
?ERROR_MSG("Failed to read ~ts: ~ts", [File, file:format_error(Why)]),
|
2017-10-09 20:46:38 +02:00
|
|
|
error
|
|
|
|
end.
|
|
|
|
|
|
|
|
meta() ->
|
|
|
|
?XA(<<"meta">>,
|
|
|
|
[{<<"name">>, <<"viewport">>},
|
|
|
|
{<<"content">>, <<"width=device-width, initial-scale=1">>}]).
|
2010-11-04 22:34:18 +01:00
|
|
|
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
%%% Index page
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
|
|
|
index_page(Lang) ->
|
2017-10-09 20:46:38 +02:00
|
|
|
HeadEls = [meta(),
|
|
|
|
?XCT(<<"title">>,
|
2021-01-11 20:18:28 +01:00
|
|
|
?T("XMPP Account Registration")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XA(<<"link">>,
|
2020-05-19 19:32:06 +02:00
|
|
|
[{<<"href">>, <<"register.css">>},
|
2013-03-14 10:33:02 +01:00
|
|
|
{<<"type">>, <<"text/css">>},
|
|
|
|
{<<"rel">>, <<"stylesheet">>}])],
|
|
|
|
Els = [?XACT(<<"h1">>,
|
|
|
|
[{<<"class">>, <<"title">>},
|
|
|
|
{<<"style">>, <<"text-align:center;">>}],
|
2021-01-11 20:18:28 +01:00
|
|
|
?T("XMPP Account Registration")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XE(<<"ul">>,
|
|
|
|
[?XE(<<"li">>,
|
2021-01-11 20:18:28 +01:00
|
|
|
[?ACT(<<"new/">>, ?T("Register an XMPP account"))]),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XE(<<"li">>,
|
2020-05-19 19:32:06 +02:00
|
|
|
[?ACT(<<"change_password/">>, ?T("Change Password"))]),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XE(<<"li">>,
|
2020-05-19 19:32:06 +02:00
|
|
|
[?ACT(<<"delete/">>,
|
2021-01-11 20:18:28 +01:00
|
|
|
?T("Unregister an XMPP account"))])])],
|
2010-11-04 22:34:18 +01:00
|
|
|
{200,
|
2013-03-14 10:33:02 +01:00
|
|
|
[{<<"Server">>, <<"ejabberd">>},
|
|
|
|
{<<"Content-Type">>, <<"text/html">>}],
|
2010-11-04 22:34:18 +01:00
|
|
|
ejabberd_web:make_xhtml(HeadEls, Els)}.
|
|
|
|
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
%%% Formulary new account GET
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
2011-04-14 10:03:02 +02:00
|
|
|
form_new_get(Host, Lang, IP) ->
|
2018-08-02 18:36:41 +02:00
|
|
|
try build_captcha_li_list(Lang, IP) of
|
|
|
|
CaptchaEls ->
|
|
|
|
form_new_get2(Host, Lang, CaptchaEls)
|
|
|
|
catch
|
|
|
|
throw:Result ->
|
2021-01-22 14:21:57 +01:00
|
|
|
?DEBUG("Unexpected result when creating a captcha: ~p", [Result]),
|
2018-08-02 18:36:41 +02:00
|
|
|
ejabberd_web:error(not_allowed)
|
|
|
|
end.
|
|
|
|
|
|
|
|
form_new_get2(Host, Lang, CaptchaEls) ->
|
2017-10-09 20:46:38 +02:00
|
|
|
HeadEls = [meta(),
|
|
|
|
?XCT(<<"title">>,
|
2021-01-11 20:18:28 +01:00
|
|
|
?T("Register an XMPP account")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XA(<<"link">>,
|
2020-05-19 19:32:06 +02:00
|
|
|
[{<<"href">>, <<"../register.css">>},
|
2013-03-14 10:33:02 +01:00
|
|
|
{<<"type">>, <<"text/css">>},
|
|
|
|
{<<"rel">>, <<"stylesheet">>}])],
|
|
|
|
Els = [?XACT(<<"h1">>,
|
|
|
|
[{<<"class">>, <<"title">>},
|
|
|
|
{<<"style">>, <<"text-align:center;">>}],
|
2021-01-11 20:18:28 +01:00
|
|
|
?T("Register an XMPP account")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XCT(<<"p">>,
|
2021-01-22 14:21:57 +01:00
|
|
|
?T("This page allows to register an XMPP "
|
|
|
|
"account in this XMPP server. Your "
|
2021-01-13 09:35:36 +01:00
|
|
|
"JID (Jabber ID) will be of the "
|
2021-01-22 14:21:57 +01:00
|
|
|
"form: username@server. Please read carefully "
|
|
|
|
"the instructions to fill correctly the "
|
2019-06-22 16:08:45 +02:00
|
|
|
"fields.")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XAE(<<"form">>,
|
|
|
|
[{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}],
|
|
|
|
[?XE(<<"ol">>,
|
|
|
|
([?XE(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
[?CT(?T("Username:")), ?C(<<" ">>),
|
2013-03-14 10:33:02 +01:00
|
|
|
?INPUTS(<<"text">>, <<"username">>, <<"">>,
|
|
|
|
<<"20">>),
|
|
|
|
?BR,
|
|
|
|
?XE(<<"ul">>,
|
|
|
|
[?XCT(<<"li">>,
|
2021-01-22 14:21:57 +01:00
|
|
|
?T("This is case insensitive: macbeth is "
|
|
|
|
"the same that MacBeth and Macbeth.")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XC(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
<<(translate:translate(Lang, ?T("Characters not allowed:")))/binary,
|
2013-03-14 10:33:02 +01:00
|
|
|
" \" & ' / : < > @ ">>)])]),
|
|
|
|
?XE(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
[?CT(?T("Server:")), ?C(<<" ">>),
|
2015-04-22 11:01:13 +02:00
|
|
|
?INPUTS(<<"text">>, <<"host">>, Host, <<"20">>)]),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XE(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
[?CT(?T("Password:")), ?C(<<" ">>),
|
2013-03-14 10:33:02 +01:00
|
|
|
?INPUTS(<<"password">>, <<"password">>, <<"">>,
|
|
|
|
<<"20">>),
|
|
|
|
?BR,
|
|
|
|
?XE(<<"ul">>,
|
|
|
|
[?XCT(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
?T("Don't tell your password to anybody, "
|
2021-01-11 20:18:28 +01:00
|
|
|
"not even the administrators of the XMPP "
|
2019-06-22 16:08:45 +02:00
|
|
|
"server.")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XCT(<<"li">>,
|
2021-01-22 14:21:57 +01:00
|
|
|
?T("You can later change your password using "
|
|
|
|
"an XMPP client.")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XCT(<<"li">>,
|
2021-01-11 20:18:28 +01:00
|
|
|
?T("Some XMPP clients can store your password "
|
2021-01-22 14:21:57 +01:00
|
|
|
"in the computer, but you should do this only "
|
|
|
|
"in your personal computer for safety reasons.")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XCT(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
?T("Memorize your password, or write it "
|
2021-01-22 14:21:57 +01:00
|
|
|
"in a paper placed in a safe place. In "
|
2021-01-11 20:18:28 +01:00
|
|
|
"XMPP there isn't an automated way "
|
2019-06-22 16:08:45 +02:00
|
|
|
"to recover your password if you forget "
|
|
|
|
"it."))])]),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XE(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
[?CT(?T("Password Verification:")), ?C(<<" ">>),
|
2013-03-14 10:33:02 +01:00
|
|
|
?INPUTS(<<"password">>, <<"password2">>, <<"">>,
|
|
|
|
<<"20">>)])]
|
|
|
|
++
|
|
|
|
CaptchaEls ++
|
|
|
|
[?XE(<<"li">>,
|
|
|
|
[?INPUTT(<<"submit">>, <<"register">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
?T("Register"))])]))])],
|
2010-11-04 22:34:18 +01:00
|
|
|
{200,
|
2013-03-14 10:33:02 +01:00
|
|
|
[{<<"Server">>, <<"ejabberd">>},
|
|
|
|
{<<"Content-Type">>, <<"text/html">>}],
|
2010-11-04 22:34:18 +01:00
|
|
|
ejabberd_web:make_xhtml(HeadEls, Els)}.
|
|
|
|
|
|
|
|
%% Copied from mod_register.erl
|
|
|
|
%% Function copied from ejabberd_logger_h.erl and customized
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
%%% Formulary new POST
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
2021-10-04 11:24:24 +02:00
|
|
|
form_new_post(Q, Ip) ->
|
2010-11-04 22:34:18 +01:00
|
|
|
case catch get_register_parameters(Q) of
|
2015-04-22 11:01:13 +02:00
|
|
|
[Username, Host, Password, Password, Id, Key] ->
|
2021-10-04 11:24:24 +02:00
|
|
|
form_new_post(Username, Host, Password, {Id, Key}, Ip);
|
2016-02-29 00:39:57 +01:00
|
|
|
[_Username, _Host, _Password, _Password2, false, false] ->
|
2013-03-14 10:33:02 +01:00
|
|
|
{error, passwords_not_identical};
|
2016-02-29 00:39:57 +01:00
|
|
|
[_Username, _Host, _Password, _Password2, Id, Key] ->
|
2013-03-14 10:33:02 +01:00
|
|
|
ejabberd_captcha:check_captcha(Id, Key),
|
|
|
|
{error, passwords_not_identical};
|
|
|
|
_ -> {error, wrong_parameters}
|
2010-11-04 22:34:18 +01:00
|
|
|
end.
|
|
|
|
|
|
|
|
get_register_parameters(Q) ->
|
2013-03-14 10:33:02 +01:00
|
|
|
lists:map(fun (Key) ->
|
|
|
|
case lists:keysearch(Key, 1, Q) of
|
|
|
|
{value, {_Key, Value}} -> Value;
|
|
|
|
false -> false
|
|
|
|
end
|
|
|
|
end,
|
2015-04-22 11:01:13 +02:00
|
|
|
[<<"username">>, <<"host">>, <<"password">>, <<"password2">>,
|
2013-03-14 10:33:02 +01:00
|
|
|
<<"id">>, <<"key">>]).
|
|
|
|
|
2021-10-04 11:24:24 +02:00
|
|
|
form_new_post(Username, Host, Password, {false, false}, Ip) ->
|
|
|
|
register_account(Username, Host, Password, Ip);
|
|
|
|
form_new_post(Username, Host, Password, {Id, Key}, Ip) ->
|
2010-11-04 22:34:18 +01:00
|
|
|
case ejabberd_captcha:check_captcha(Id, Key) of
|
2013-03-14 10:33:02 +01:00
|
|
|
captcha_valid ->
|
2021-10-04 11:24:24 +02:00
|
|
|
register_account(Username, Host, Password, Ip);
|
2013-03-14 10:33:02 +01:00
|
|
|
captcha_non_valid -> {error, captcha_non_valid};
|
|
|
|
captcha_not_found -> {error, captcha_non_valid}
|
2010-11-04 22:34:18 +01:00
|
|
|
end.
|
|
|
|
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
%%% Formulary Captcha support for new GET/POST
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
2011-04-14 10:03:02 +02:00
|
|
|
build_captcha_li_list(Lang, IP) ->
|
2010-11-04 22:34:18 +01:00
|
|
|
case ejabberd_captcha:is_feature_available() of
|
2013-03-14 10:33:02 +01:00
|
|
|
true -> build_captcha_li_list2(Lang, IP);
|
|
|
|
false -> []
|
2010-11-04 22:34:18 +01:00
|
|
|
end.
|
|
|
|
|
2011-04-14 10:03:02 +02:00
|
|
|
build_captcha_li_list2(Lang, IP) ->
|
2013-03-14 10:33:02 +01:00
|
|
|
SID = <<"">>,
|
|
|
|
From = #jid{user = <<"">>, server = <<"test">>,
|
|
|
|
resource = <<"">>},
|
|
|
|
To = #jid{user = <<"">>, server = <<"test">>,
|
|
|
|
resource = <<"">>},
|
2010-11-04 22:34:18 +01:00
|
|
|
Args = [],
|
2019-06-14 11:33:26 +02:00
|
|
|
case ejabberd_captcha:create_captcha(
|
|
|
|
SID, From, To, Lang, IP, Args) of
|
|
|
|
{ok, Id, _, _} ->
|
|
|
|
case ejabberd_captcha:build_captcha_html(Id, Lang) of
|
|
|
|
{_, {CImg, CText, CId, CKey}} ->
|
|
|
|
[?XE(<<"li">>,
|
|
|
|
[CText, ?C(<<" ">>), CId, CKey, ?BR, CImg])];
|
|
|
|
Error ->
|
|
|
|
throw(Error)
|
|
|
|
end;
|
|
|
|
Error ->
|
|
|
|
throw(Error)
|
2011-04-14 10:03:02 +02:00
|
|
|
end.
|
2010-11-04 22:34:18 +01:00
|
|
|
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
%%% Formulary change password GET
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
|
|
|
form_changepass_get(Host, Lang) ->
|
2017-10-09 20:46:38 +02:00
|
|
|
HeadEls = [meta(),
|
2019-06-22 16:08:45 +02:00
|
|
|
?XCT(<<"title">>, ?T("Change Password")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XA(<<"link">>,
|
2020-05-19 19:32:06 +02:00
|
|
|
[{<<"href">>, <<"../register.css">>},
|
2013-03-14 10:33:02 +01:00
|
|
|
{<<"type">>, <<"text/css">>},
|
|
|
|
{<<"rel">>, <<"stylesheet">>}])],
|
|
|
|
Els = [?XACT(<<"h1">>,
|
|
|
|
[{<<"class">>, <<"title">>},
|
|
|
|
{<<"style">>, <<"text-align:center;">>}],
|
2019-06-22 16:08:45 +02:00
|
|
|
?T("Change Password")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XAE(<<"form">>,
|
|
|
|
[{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}],
|
|
|
|
[?XE(<<"ol">>,
|
|
|
|
[?XE(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
[?CT(?T("Username:")), ?C(<<" ">>),
|
2013-03-14 10:33:02 +01:00
|
|
|
?INPUTS(<<"text">>, <<"username">>, <<"">>,
|
|
|
|
<<"20">>)]),
|
|
|
|
?XE(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
[?CT(?T("Server:")), ?C(<<" ">>),
|
2016-02-04 21:31:16 +01:00
|
|
|
?INPUTS(<<"text">>, <<"host">>, Host, <<"20">>)]),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XE(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
[?CT(?T("Old Password:")), ?C(<<" ">>),
|
2013-03-14 10:33:02 +01:00
|
|
|
?INPUTS(<<"password">>, <<"passwordold">>, <<"">>,
|
|
|
|
<<"20">>)]),
|
|
|
|
?XE(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
[?CT(?T("New Password:")), ?C(<<" ">>),
|
2013-03-14 10:33:02 +01:00
|
|
|
?INPUTS(<<"password">>, <<"password">>, <<"">>,
|
|
|
|
<<"20">>)]),
|
|
|
|
?XE(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
[?CT(?T("Password Verification:")), ?C(<<" ">>),
|
2013-03-14 10:33:02 +01:00
|
|
|
?INPUTS(<<"password">>, <<"password2">>, <<"">>,
|
|
|
|
<<"20">>)]),
|
|
|
|
?XE(<<"li">>,
|
|
|
|
[?INPUTT(<<"submit">>, <<"changepass">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
?T("Change Password"))])])])],
|
2010-11-04 22:34:18 +01:00
|
|
|
{200,
|
2013-03-14 10:33:02 +01:00
|
|
|
[{<<"Server">>, <<"ejabberd">>},
|
|
|
|
{<<"Content-Type">>, <<"text/html">>}],
|
2010-11-04 22:34:18 +01:00
|
|
|
ejabberd_web:make_xhtml(HeadEls, Els)}.
|
|
|
|
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
%%% Formulary change password POST
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
2016-02-04 21:31:16 +01:00
|
|
|
form_changepass_post(Q) ->
|
2010-11-04 22:34:18 +01:00
|
|
|
case catch get_changepass_parameters(Q) of
|
2016-02-04 21:31:16 +01:00
|
|
|
[Username, Host, PasswordOld, Password, Password] ->
|
2013-03-14 10:33:02 +01:00
|
|
|
try_change_password(Username, Host, PasswordOld,
|
|
|
|
Password);
|
2016-02-29 00:39:57 +01:00
|
|
|
[_Username, _Host, _PasswordOld, _Password, _Password2] ->
|
2013-03-14 10:33:02 +01:00
|
|
|
{error, passwords_not_identical};
|
|
|
|
_ -> {error, wrong_parameters}
|
2010-11-04 22:34:18 +01:00
|
|
|
end.
|
|
|
|
|
|
|
|
get_changepass_parameters(Q) ->
|
|
|
|
%% @spec(Username,Host,PasswordOld,Password) -> {atomic, ok} |
|
|
|
|
%% {error, account_doesnt_exist} |
|
|
|
|
%% {error, password_not_changed} |
|
|
|
|
%% {error, password_incorrect}
|
2013-03-14 10:33:02 +01:00
|
|
|
lists:map(fun (Key) ->
|
|
|
|
{value, {_Key, Value}} = lists:keysearch(Key, 1, Q),
|
|
|
|
Value
|
|
|
|
end,
|
2016-02-04 21:31:16 +01:00
|
|
|
[<<"username">>, <<"host">>, <<"passwordold">>, <<"password">>,
|
2013-03-14 10:33:02 +01:00
|
|
|
<<"password2">>]).
|
|
|
|
|
|
|
|
try_change_password(Username, Host, PasswordOld,
|
|
|
|
Password) ->
|
|
|
|
try change_password(Username, Host, PasswordOld,
|
|
|
|
Password)
|
|
|
|
of
|
|
|
|
{atomic, ok} -> {atomic, ok}
|
2010-11-04 22:34:18 +01:00
|
|
|
catch
|
2013-03-14 10:33:02 +01:00
|
|
|
error:{badmatch, Error} -> {error, Error}
|
2010-11-04 22:34:18 +01:00
|
|
|
end.
|
|
|
|
|
2013-03-14 10:33:02 +01:00
|
|
|
change_password(Username, Host, PasswordOld,
|
|
|
|
Password) ->
|
2010-11-04 22:34:18 +01:00
|
|
|
account_exists = check_account_exists(Username, Host),
|
2013-03-14 10:33:02 +01:00
|
|
|
password_correct = check_password(Username, Host,
|
|
|
|
PasswordOld),
|
|
|
|
ok = ejabberd_auth:set_password(Username, Host,
|
|
|
|
Password),
|
2010-11-04 22:34:18 +01:00
|
|
|
case check_password(Username, Host, Password) of
|
2013-03-14 10:33:02 +01:00
|
|
|
password_correct -> {atomic, ok};
|
|
|
|
password_incorrect -> {error, password_not_changed}
|
2010-11-04 22:34:18 +01:00
|
|
|
end.
|
|
|
|
|
|
|
|
check_account_exists(Username, Host) ->
|
2017-05-11 14:49:06 +02:00
|
|
|
case ejabberd_auth:user_exists(Username, Host) of
|
2013-03-14 10:33:02 +01:00
|
|
|
true -> account_exists;
|
|
|
|
false -> account_doesnt_exist
|
2010-11-04 22:34:18 +01:00
|
|
|
end.
|
|
|
|
|
|
|
|
check_password(Username, Host, Password) ->
|
2015-04-09 03:21:09 +02:00
|
|
|
case ejabberd_auth:check_password(Username, <<"">>, Host,
|
2013-03-14 10:33:02 +01:00
|
|
|
Password)
|
|
|
|
of
|
|
|
|
true -> password_correct;
|
|
|
|
false -> password_incorrect
|
2010-11-04 22:34:18 +01:00
|
|
|
end.
|
|
|
|
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
%%% Formulary delete account GET
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
|
|
|
form_del_get(Host, Lang) ->
|
2017-10-09 20:46:38 +02:00
|
|
|
HeadEls = [meta(),
|
|
|
|
?XCT(<<"title">>,
|
2021-01-11 20:18:28 +01:00
|
|
|
?T("Unregister an XMPP account")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XA(<<"link">>,
|
2020-05-19 19:32:06 +02:00
|
|
|
[{<<"href">>, <<"../register.css">>},
|
2013-03-14 10:33:02 +01:00
|
|
|
{<<"type">>, <<"text/css">>},
|
|
|
|
{<<"rel">>, <<"stylesheet">>}])],
|
|
|
|
Els = [?XACT(<<"h1">>,
|
|
|
|
[{<<"class">>, <<"title">>},
|
|
|
|
{<<"style">>, <<"text-align:center;">>}],
|
2021-01-11 20:18:28 +01:00
|
|
|
?T("Unregister an XMPP account")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XCT(<<"p">>,
|
2021-01-22 14:21:57 +01:00
|
|
|
?T("This page allows to unregister an XMPP "
|
|
|
|
"account in this XMPP server.")),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XAE(<<"form">>,
|
|
|
|
[{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}],
|
|
|
|
[?XE(<<"ol">>,
|
|
|
|
[?XE(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
[?CT(?T("Username:")), ?C(<<" ">>),
|
2013-03-14 10:33:02 +01:00
|
|
|
?INPUTS(<<"text">>, <<"username">>, <<"">>,
|
|
|
|
<<"20">>)]),
|
|
|
|
?XE(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
[?CT(?T("Server:")), ?C(<<" ">>),
|
2016-02-04 21:31:16 +01:00
|
|
|
?INPUTS(<<"text">>, <<"host">>, Host, <<"20">>)]),
|
2013-03-14 10:33:02 +01:00
|
|
|
?XE(<<"li">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
[?CT(?T("Password:")), ?C(<<" ">>),
|
2013-03-14 10:33:02 +01:00
|
|
|
?INPUTS(<<"password">>, <<"password">>, <<"">>,
|
|
|
|
<<"20">>)]),
|
|
|
|
?XE(<<"li">>,
|
|
|
|
[?INPUTT(<<"submit">>, <<"unregister">>,
|
2019-06-22 16:08:45 +02:00
|
|
|
?T("Unregister"))])])])],
|
2010-11-04 22:34:18 +01:00
|
|
|
{200,
|
2013-03-14 10:33:02 +01:00
|
|
|
[{<<"Server">>, <<"ejabberd">>},
|
|
|
|
{<<"Content-Type">>, <<"text/html">>}],
|
2010-11-04 22:34:18 +01:00
|
|
|
ejabberd_web:make_xhtml(HeadEls, Els)}.
|
|
|
|
|
2021-10-04 11:24:24 +02:00
|
|
|
%% @spec(Username, Host, Password, Ip) -> {success, ok, {Username, Host, Password} |
|
2010-11-04 22:34:18 +01:00
|
|
|
%% {success, exists, {Username, Host, Password}} |
|
|
|
|
%% {error, not_allowed} |
|
|
|
|
%% {error, invalid_jid}
|
2021-10-04 11:24:24 +02:00
|
|
|
register_account(Username, Host, Password, Ip) ->
|
2021-09-05 13:24:51 +02:00
|
|
|
try mod_register_opt:access(Host) of
|
|
|
|
Access ->
|
|
|
|
case jid:make(Username, Host) of
|
|
|
|
error -> {error, invalid_jid};
|
|
|
|
JID ->
|
|
|
|
case acl:match_rule(Host, Access, JID) of
|
|
|
|
deny -> {error, not_allowed};
|
2021-10-04 11:24:24 +02:00
|
|
|
allow -> register_account2(Username, Host, Password, Ip)
|
2021-09-05 13:24:51 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
catch _:{module_not_loaded, mod_register, _Host} ->
|
|
|
|
{error, host_unknown}
|
2011-07-27 12:25:51 +02:00
|
|
|
end.
|
2013-03-14 10:33:02 +01:00
|
|
|
|
2021-10-04 11:24:24 +02:00
|
|
|
register_account2(Username, Host, Password, Ip) ->
|
2021-12-03 12:16:20 +01:00
|
|
|
case mod_register:try_register(Username, Host, Password, Ip, ?MODULE)
|
2013-03-14 10:33:02 +01:00
|
|
|
of
|
2017-05-11 13:37:21 +02:00
|
|
|
ok ->
|
|
|
|
{success, ok, {Username, Host, Password}};
|
2013-03-14 10:33:02 +01:00
|
|
|
Other -> Other
|
2010-11-04 22:34:18 +01:00
|
|
|
end.
|
|
|
|
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
%%% Formulary delete POST
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
2016-02-04 21:31:16 +01:00
|
|
|
form_del_post(Q) ->
|
2010-11-04 22:34:18 +01:00
|
|
|
case catch get_unregister_parameters(Q) of
|
2016-02-04 21:31:16 +01:00
|
|
|
[Username, Host, Password] ->
|
2013-03-14 10:33:02 +01:00
|
|
|
try_unregister_account(Username, Host, Password);
|
|
|
|
_ -> {error, wrong_parameters}
|
2010-11-04 22:34:18 +01:00
|
|
|
end.
|
|
|
|
|
|
|
|
get_unregister_parameters(Q) ->
|
|
|
|
%% @spec(Username, Host, Password) -> {atomic, ok} |
|
|
|
|
%% {error, account_doesnt_exist} |
|
|
|
|
%% {error, account_exists} |
|
|
|
|
%% {error, password_incorrect}
|
2013-03-14 10:33:02 +01:00
|
|
|
lists:map(fun (Key) ->
|
|
|
|
{value, {_Key, Value}} = lists:keysearch(Key, 1, Q),
|
|
|
|
Value
|
|
|
|
end,
|
2016-02-04 21:31:16 +01:00
|
|
|
[<<"username">>, <<"host">>, <<"password">>]).
|
2013-03-14 10:33:02 +01:00
|
|
|
|
2010-11-04 22:34:18 +01:00
|
|
|
try_unregister_account(Username, Host, Password) ->
|
|
|
|
try unregister_account(Username, Host, Password) of
|
2013-03-14 10:33:02 +01:00
|
|
|
{atomic, ok} -> {atomic, ok}
|
2010-11-04 22:34:18 +01:00
|
|
|
catch
|
2013-03-14 10:33:02 +01:00
|
|
|
error:{badmatch, Error} -> {error, Error}
|
2010-11-04 22:34:18 +01:00
|
|
|
end.
|
|
|
|
|
|
|
|
unregister_account(Username, Host, Password) ->
|
|
|
|
account_exists = check_account_exists(Username, Host),
|
2013-03-14 10:33:02 +01:00
|
|
|
password_correct = check_password(Username, Host,
|
|
|
|
Password),
|
|
|
|
ok = ejabberd_auth:remove_user(Username, Host,
|
|
|
|
Password),
|
|
|
|
account_doesnt_exist = check_account_exists(Username,
|
|
|
|
Host),
|
2010-11-04 22:34:18 +01:00
|
|
|
{atomic, ok}.
|
|
|
|
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
%%% Error texts
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
|
|
|
get_error_text({error, captcha_non_valid}) ->
|
2021-01-22 14:21:57 +01:00
|
|
|
?T("The captcha you entered is wrong");
|
2019-06-05 18:28:35 +02:00
|
|
|
get_error_text({error, exists}) ->
|
2019-06-22 16:08:45 +02:00
|
|
|
?T("The account already exists");
|
2010-11-04 22:34:18 +01:00
|
|
|
get_error_text({error, password_incorrect}) ->
|
2019-06-22 16:08:45 +02:00
|
|
|
?T("Incorrect password");
|
2021-09-05 13:24:51 +02:00
|
|
|
get_error_text({error, host_unknown}) ->
|
|
|
|
?T("Host unknown");
|
2010-11-04 22:34:18 +01:00
|
|
|
get_error_text({error, account_doesnt_exist}) ->
|
2019-06-22 16:08:45 +02:00
|
|
|
?T("Account doesn't exist");
|
2010-11-04 22:34:18 +01:00
|
|
|
get_error_text({error, account_exists}) ->
|
2021-01-13 16:01:43 +01:00
|
|
|
?T("The account was not unregistered");
|
2010-11-04 22:34:18 +01:00
|
|
|
get_error_text({error, password_not_changed}) ->
|
2019-06-22 16:08:45 +02:00
|
|
|
?T("The password was not changed");
|
2010-11-04 22:34:18 +01:00
|
|
|
get_error_text({error, passwords_not_identical}) ->
|
2019-06-22 16:08:45 +02:00
|
|
|
?T("The passwords are different");
|
2010-11-04 22:34:18 +01:00
|
|
|
get_error_text({error, wrong_parameters}) ->
|
2021-10-04 11:14:56 +02:00
|
|
|
?T("Wrong parameters in the web formulary");
|
|
|
|
get_error_text({error, Why}) ->
|
|
|
|
mod_register:format_error(Why).
|
2015-06-01 14:38:27 +02:00
|
|
|
|
2018-01-23 08:54:52 +01:00
|
|
|
mod_options(_) ->
|
|
|
|
[].
|
2020-01-08 10:24:51 +01:00
|
|
|
|
|
|
|
mod_doc() ->
|
|
|
|
#{desc =>
|
|
|
|
[?T("This module provides a web page where users can:"), "",
|
|
|
|
?T("- Register a new account on the server."), "",
|
|
|
|
?T("- Change the password from an existing account on the server."), "",
|
2021-01-13 16:01:43 +01:00
|
|
|
?T("- Unregister an existing account on the server."), "",
|
2021-08-18 13:40:09 +02:00
|
|
|
?T("This module supports http://../basic/#captcha[CAPTCHA] "
|
|
|
|
"to register a new account. "
|
|
|
|
"To enable this feature, configure the "
|
|
|
|
"top-level _`captcha_cmd`_ and "
|
|
|
|
"top-level _`captcha_url`_ options."), "",
|
|
|
|
?T("As an example usage, the users of the host 'localhost' can "
|
|
|
|
"visit the page: 'https://localhost:5280/register/' It is "
|
2021-01-22 14:21:57 +01:00
|
|
|
"important to include the last / character in the URL, "
|
|
|
|
"otherwise the subpages URL will be incorrect."), "",
|
2021-08-18 13:40:09 +02:00
|
|
|
?T("This module is enabled in 'listen' -> 'ejabberd_http' -> "
|
|
|
|
"http://../listen-options/#request-handlers[request_handlers], "
|
|
|
|
"no need to enable in 'modules'."),
|
|
|
|
?T("The module depends on _`mod_register`_ where all the "
|
|
|
|
"configuration is performed.")],
|
|
|
|
example =>
|
|
|
|
["listen:",
|
|
|
|
" -",
|
|
|
|
" port: 5280",
|
|
|
|
" module: ejabberd_http",
|
|
|
|
" request_handlers:",
|
|
|
|
" /register: mod_register_web",
|
|
|
|
"",
|
|
|
|
"modules:",
|
|
|
|
" mod_register: {}"]}.
|