From b5d03f13b14ad72cdbe9b445e79c5ba3844541ff Mon Sep 17 00:00:00 2001 From: Kamil Waz Date: Fri, 28 Oct 2022 14:45:41 +0200 Subject: [PATCH] Convert ejabberd_auth to gen_hook --- src/auth/ejabberd_auth.erl | 36 +++++++------- src/auth/ejabberd_auth_anonymous.erl | 70 +++++++++++++++------------- src/mongoose_hooks.erl | 12 +++-- test/mongoose_cleanup_SUITE.erl | 4 +- 4 files changed, 66 insertions(+), 56 deletions(-) diff --git a/src/auth/ejabberd_auth.erl b/src/auth/ejabberd_auth.erl index dd6abb53ca..b3f0eb9c39 100644 --- a/src/auth/ejabberd_auth.erl +++ b/src/auth/ejabberd_auth.erl @@ -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"). @@ -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} ]. @@ -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 diff --git a/src/auth/ejabberd_auth_anonymous.erl b/src/auth/ejabberd_auth_anonymous.erl index f30b50794e..214943e284 100644 --- a/src/auth/ejabberd_auth_anonymous.erl +++ b/src/auth/ejabberd_auth_anonymous.erl @@ -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). @@ -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"). @@ -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{ @@ -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'. @@ -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 diff --git a/src/mongoose_hooks.erl b/src/mongoose_hooks.erl index 9d9ca4e120..750fe6b99a 100644 --- a/src/mongoose_hooks.erl +++ b/src/mongoose_hooks.erl @@ -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(), @@ -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 diff --git a/test/mongoose_cleanup_SUITE.erl b/test/mongoose_cleanup_SUITE.erl index d28cf403b6..870b597334 100644 --- a/test/mongoose_cleanup_SUITE.erl +++ b/test/mongoose_cleanup_SUITE.erl @@ -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).