Skip to content

Commit

Permalink
Convert ejabberd_auth to gen_hook
Browse files Browse the repository at this point in the history
  • Loading branch information
Kamil Waz committed Oct 28, 2022
1 parent dc32b41 commit b5d03f1
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 56 deletions.
36 changes: 17 additions & 19 deletions src/auth/ejabberd_auth.erl
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,11 @@

%% Hook handlers
-export([remove_domain/3]).
-export([does_user_exist/4]).
-export([on_does_user_exist/3]).

-ignore_xref([
auth_methods/1, auth_modules/1, check_password/4, does_user_exist/4,
get_vh_registered_users/2, get_vh_registered_users_number/2,
start/1, stop/1]).
auth_methods/1, auth_modules/1, check_password/4, get_vh_registered_users/2,
get_vh_registered_users_number/2, start/1, stop/1]).

-include("mongoose.hrl").
-include("jlib.hrl").
Expand Down Expand Up @@ -103,27 +102,21 @@ start(HostType) ->
ensure_metrics(HostType),
F = fun(Mod) -> mongoose_gen_auth:start(Mod, HostType) end,
call_auth_modules_for_host_type(HostType, F, #{op => map}),
ejabberd_hooks:add(legacy_hooks(HostType)),
gen_hook:add_handlers(hooks(HostType)),
ok.

-spec stop(HostType :: mongooseim:host_type()) -> 'ok'.
stop(HostType) ->
ejabberd_hooks:delete(legacy_hooks(HostType)),
gen_hook:delete_handlers(hooks(HostType)),
F = fun(Mod) -> mongoose_gen_auth:stop(Mod, HostType) end,
call_auth_modules_for_host_type(HostType, F, #{op => map}),
ok.

legacy_hooks(HostType) ->
[
%% These hooks must run in between those of mod_cache_users
{does_user_exist, HostType, ?MODULE, does_user_exist, 50}
].

-spec hooks(mongooseim:host_type()) -> gen_hook:hook_list().
hooks(HostType) ->
[
%% These hooks must run in between those of mod_cache_users
{does_user_exist, HostType, fun ?MODULE:on_does_user_exist/3, #{}, 50},
%% It is important that this handler happens _before_ all other modules
{remove_domain, HostType, fun ?MODULE:remove_domain/3, #{}, 10}
].
Expand Down Expand Up @@ -316,14 +309,19 @@ does_user_exist(HostType, Jid, RequestType) ->

%% @doc does_user_exist hook handler
%% Returns 'false' in case of an error
-spec does_user_exist(boolean(), mongooseim:host_type(), jid:jid(), exist_type()) -> boolean().
does_user_exist(false, HostType, Jid, stored) ->
true =:= does_stored_user_exist(HostType, Jid);
does_user_exist(false, HostType, #jid{luser = LUser, lserver = LServer}, with_anonymous) ->
-spec on_does_user_exist(Acc, Params, Extra) -> {ok, Acc} when
Acc :: boolean(),
Params :: map(),
Extra :: map().
on_does_user_exist(false, #{jid := Jid, request_type := stored}, #{host_type := HostType}) ->
{ok, true =:= does_stored_user_exist(HostType, Jid)};
on_does_user_exist(false,
#{jid := #jid{luser = LUser, lserver = LServer}, request_type := with_anonymous},
#{host_type := HostType}) ->
F = fun(Mod) -> does_user_exist_in_module(HostType, LUser, LServer, Mod) end,
call_auth_modules_for_host_type(HostType, F, #{default => false, metric => does_user_exist});
does_user_exist(Status, _, _, _) ->
Status.
{ok, call_auth_modules_for_host_type(HostType, F, #{default => false, metric => does_user_exist})};
on_does_user_exist(Status, _, _) ->
{ok, Status}.

%% @doc Returns true if the user exists in the DB
%% In case of a backend error, it is propagated to the caller
Expand Down
70 changes: 38 additions & 32 deletions src/auth/ejabberd_auth_anonymous.erl
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
-export([start/1,
stop/1,
config_spec/0,
register_connection/5,
unregister_connection/5,
session_cleanup/5
register_connection/3,
unregister_connection/3,
session_cleanup/3
]).

-behaviour(mongoose_gen_auth).
Expand All @@ -51,8 +51,7 @@
-export([check_password/4,
check_password/6]).

-ignore_xref([register_connection/5, session_cleanup/5, unregister_connection/5,
login/3]).
-ignore_xref([login/3]).

-include("mongoose.hrl").
-include("jlib.hrl").
Expand All @@ -73,18 +72,22 @@ start(HostType) ->
{attributes, record_info(fields, anonymous)}]),
mnesia:add_table_copy(anonymous, node(), ram_copies),
%% The hooks are needed to add / remove users from the anonymous tables
ejabberd_hooks:add(sm_register_connection_hook, HostType, ?MODULE, register_connection, 100),
ejabberd_hooks:add(sm_remove_connection_hook, HostType, ?MODULE, unregister_connection, 100),
ejabberd_hooks:add(session_cleanup, HostType, ?MODULE, session_cleanup, 50),
gen_hook:add_handlers(hooks(HostType)),
ok.

-spec stop(mongooseim:host_type()) -> ok.
stop(HostType) ->
ejabberd_hooks:delete(sm_register_connection_hook, HostType, ?MODULE, register_connection, 100),
ejabberd_hooks:delete(sm_remove_connection_hook, HostType, ?MODULE, unregister_connection, 100),
ejabberd_hooks:delete(session_cleanup, HostType, ?MODULE, session_cleanup, 50),
gen_hook:delete_handlers(hooks(HostType)),
ok.

-spec hooks(mongooseim:host_type()) -> gen_hook:hook_list().
hooks(HostType) ->
[
{sm_register_connection_hook, HostType, fun ?MODULE:register_connection/3, #{}, 100},
{sm_remove_connection_hook, HostType, fun ?MODULE:unregister_connection/3, #{}, 100},
{session_cleanup, HostType, fun ?MODULE:session_cleanup/3, #{}, 50}
].

-spec config_spec() -> mongoose_config_spec:config_section().
config_spec() ->
#section{
Expand Down Expand Up @@ -132,32 +135,35 @@ remove_connection(SID, LUser, LServer) ->


%% @doc Register connection
-spec register_connection(Acc,
HostType :: mongooseim:host_type(),
SID :: ejabberd_sm:sid(),
JID :: jid:jid(),
Info :: ejabberd_sm:info()) -> Acc when Acc :: any().
register_connection(Acc, HostType, SID, #jid{luser = LUser, lserver = LServer},
#{auth_module := AuthModule})
-spec register_connection(Acc, Params, Extra) -> {ok, Acc} when
Acc :: term(),
Params :: map(),
Extra :: map().
register_connection(Acc,
#{sid := SID,
jid := #jid{luser = LUser, lserver = LServer},
info := #{auth_module := AuthModule}},
#{host_type := HostType})
when AuthModule =:= ejabberd_auth_anonymous; % login_anon
AuthModule =:= cyrsasl_anonymous -> % sasl_anon
mongoose_hooks:register_user(HostType, LServer, LUser),
US = {LUser, LServer},
mnesia:sync_dirty(fun() -> mnesia:write(#anonymous{us = US, sid = SID}) end),
Acc;
register_connection(Acc, _HostType, _SID, _JID, _Info) ->
Acc.
{ok, Acc};
register_connection(Acc, _Params, _Extra) ->
{ok, Acc}.

%% @doc Remove an anonymous user from the anonymous users table
-spec unregister_connection(Acc, SID :: ejabberd_sm:sid(), JID :: jid:jid(),
any(), ejabberd_sm:close_reason()) -> Acc
when Acc :: mongoose_acc:t().
unregister_connection(Acc, SID, #jid{luser = LUser, lserver = LServer}, _, _) ->
-spec unregister_connection(Acc, Params, Extra) -> {ok, Acc} when
Acc :: mongoose_acc:t(),
Params :: map(),
Extra :: map().
unregister_connection(Acc, #{sid := SID, jid := #jid{luser = LUser, lserver = LServer}}, _Extra) ->
purge_hook(does_anonymous_user_exist(LUser, LServer),
mongoose_acc:host_type(Acc),
LUser, LServer),
remove_connection(SID, LUser, LServer),
Acc.
{ok, Acc}.

%% @doc Launch the hook to purge user data only for anonymous users.
-spec purge_hook(boolean(), mongooseim:host_type(), jid:luser(), jid:lserver()) -> 'ok'.
Expand All @@ -170,13 +176,13 @@ purge_hook(true, HostType, LUser, LServer) ->
element => undefined }),
mongoose_hooks:anonymous_purge_hook(LServer, Acc, LUser).

-spec session_cleanup(Acc :: map(), LUser :: jid:luser(),
LServer :: jid:lserver(),
LResource :: jid:lresource(),
SID :: ejabberd_sm:sid()) -> any().
session_cleanup(Acc, LUser, LServer, _LResource, SID) ->
-spec session_cleanup(Acc, Params, Extra) -> {ok, Acc} when
Acc :: mongoose_acc:t(),
Params :: map(),
Extra :: map().
session_cleanup(Acc, #{sid := SID, user := LUser, server := LServer}, _Extra) ->
remove_connection(SID, LUser, LServer),
Acc.
{ok, Acc}.

%% ---------------------------------
%% Specific anonymous auth functions
Expand Down
12 changes: 8 additions & 4 deletions src/mongoose_hooks.erl
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,10 @@ auth_failed(HostType, Server, Username) ->
RequestType :: ejabberd_auth:exist_type(),
Result :: boolean().
does_user_exist(HostType, Jid, RequestType) ->
run_hook_for_host_type(does_user_exist, HostType, false,
[HostType, Jid, RequestType]).
Params = #{jid => Jid, request_type => RequestType},
Args = [HostType, Jid, RequestType],
ParamsWithLegacyArgs = ejabberd_hooks:add_args(Params, Args),
run_hook_for_host_type(does_user_exist, HostType, false, ParamsWithLegacyArgs).

-spec remove_domain(HostType, Domain) -> Result when
HostType :: binary(),
Expand Down Expand Up @@ -402,9 +404,11 @@ resend_offline_messages_hook(Acc, JID) ->
SID :: ejabberd_sm:sid(),
Result :: mongoose_acc:t().
session_cleanup(Server, Acc, User, Resource, SID) ->
Params = #{user => User, server => Server, resource => Resource, sid => SID},
Args = [User, Server, Resource, SID],
ParamsWithLegacyArgs = ejabberd_hooks:add_args(Params, Args),
HostType = mongoose_acc:host_type(Acc),
run_hook_for_host_type(session_cleanup, HostType, Acc,
[User, Server, Resource, SID]).
run_hook_for_host_type(session_cleanup, HostType, Acc, ParamsWithLegacyArgs).

%%% @doc The `set_vcard' hook is called when the caller wants to set the VCard.
-spec set_vcard(HostType, UserJID, VCard) -> Result when
Expand Down
4 changes: 3 additions & 1 deletion test/mongoose_cleanup_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ auth_anonymous(_Config) ->
{U, S, R, JID, SID} = get_fake_session(),
ejabberd_auth_anonymous:start(HostType),
Info = #{auth_module => cyrsasl_anonymous},
ejabberd_auth_anonymous:register_connection(#{}, HostType, SID, JID, Info),
ejabberd_auth_anonymous:register_connection(#{},
#{sid => SID, jid => JID, info => Info},
#{host_type => HostType}),
true = ejabberd_auth_anonymous:does_user_exist(HostType, U, S),
mongoose_hooks:session_cleanup(S, new_acc(S), U, R, SID),
false = ejabberd_auth_anonymous:does_user_exist(HostType, U, S).
Expand Down

0 comments on commit b5d03f1

Please sign in to comment.