Skip to content

Commit

Permalink
Merge pull request #3135 from esl/multitenancy/ejabberd_users
Browse files Browse the repository at this point in the history
Multitenancy for ejabberd users

This erases ejabberd_users and creates a new module called mongoose_users that implements pretty much the same cache idea, but creates a table per host_type, and implements the remove_domain hook.

It also chooses to extract the host_type from the accumulator in some places where we can be sure we do have a host_type, like, when run inside user_send_packet, filter_local_packet, or iq handlers.

Implementation is fine for now, mongoose_users must be reimplemented with the proper caching solution once we pick one.
  • Loading branch information
DenysGonchar authored May 28, 2021
2 parents e896371 + c51ebed commit 2a0d26a
Show file tree
Hide file tree
Showing 12 changed files with 176 additions and 244 deletions.
8 changes: 2 additions & 6 deletions big_tests/tests/ejabberdctl_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,8 @@ end_per_group(Rosters, Config) when (Rosters == roster) or (Rosters == roster_ad
true ->
SB = string_to_binary(S),
UB = string_to_binary(U),
Acc = rpc(mim(), mongoose_acc, new,
[#{ location => {?MODULE, ?FUNCTION_NAME, ?LINE},
lserver => SB,
host_type => SB,
element => undefined }]),
rpc(mim(), mongoose_hooks, remove_user, [SB, Acc, UB]);
Acc = mongoose_helper:new_mongoose_acc(SB),
rpc(mim(), mongoose_hooks, remove_user, [Acc, SB, UB]);
_ ->
ok
end
Expand Down
7 changes: 4 additions & 3 deletions big_tests/tests/mam_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -3046,9 +3046,10 @@ check_user_exist(Config) ->
JID = mongoose_helper:make_jid(AdminU, AdminS),
ok = rpc(mim(), ejabberd_auth, try_register, [JID, AdminP]),
%% admin user already registered
true = rpc(mim(), ejabberd_users, does_user_exist, [JID]),
false = rpc(mim(), ejabberd_users, does_user_exist, [mongoose_helper:make_jid(<<"fake-user">>, AdminS)]),
false = rpc(mim(), ejabberd_users, does_user_exist, [mongoose_helper:make_jid(AdminU, <<"fake-domain">>)]),
{ok, HostType} = rpc(mim(), mongoose_domain_core, get_host_type, [AdminS]),
true = rpc(mim(), mongoose_users, does_user_exist, [HostType, JID]),
false = rpc(mim(), mongoose_users, does_user_exist, [HostType, mongoose_helper:make_jid(<<"fake-user">>, AdminS)]),
false = rpc(mim(), mongoose_users, does_user_exist, [HostType, mongoose_helper:make_jid(AdminU, <<"fake-domain">>)]),
%% cleanup
ok = rpc(mim(), ejabberd_auth, remove_user, [JID]).

Expand Down
14 changes: 12 additions & 2 deletions big_tests/tests/mongoose_helper.erl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
-module(mongoose_helper).

-include_lib("kernel/include/logger.hrl").

%% API

-export([is_rdbms_enabled/1,
Expand Down Expand Up @@ -42,6 +44,7 @@
-export([get_listener_opts/2]).
-export([restart_listener_with_opts/3]).
-export([should_minio_be_running/1]).
-export([new_mongoose_acc/1]).

-import(distributed_helper, [mim/0, rpc/4]).

Expand Down Expand Up @@ -114,12 +117,12 @@ clear_last_activity(Config, User) ->

do_clear_last_activity(Config, User) when is_atom(User)->
[U, S, _P] = escalus_users:get_usp(Config, carol),
Acc = new_mongoose_acc({?MODULE, ?FUNCTION_NAME, ?LINE}, S),
Acc = new_mongoose_acc(?LOCATION, S),
successful_rpc(mod_last, remove_user, [Acc, U, S]);
do_clear_last_activity(_Config, User) when is_binary(User) ->
U = escalus_utils:get_username(User),
S = escalus_utils:get_server(User),
Acc = new_mongoose_acc({?MODULE, ?FUNCTION_NAME, ?LINE}, S),
Acc = new_mongoose_acc(?LOCATION, S),
successful_rpc(mod_last, remove_user, [Acc, U, S]);
do_clear_last_activity(Config, Users) when is_list(Users) ->
lists:foreach(fun(User) -> do_clear_last_activity(Config, User) end, Users).
Expand All @@ -129,6 +132,13 @@ new_mongoose_acc(Location, Server) ->
lserver => Server,
element => undefined }]).

new_mongoose_acc(Server) ->
{ok, HostType} = rpc(mim(), mongoose_domain_core, get_host_type, [Server]),
successful_rpc(mongoose_acc, new, [#{ location => ?LOCATION,
lserver => Server,
host_type => HostType,
element => undefined }]).

clear_caps_cache(CapsNode) ->
ok = rpc(mim(), mod_caps, delete_caps, [CapsNode]).

Expand Down
4 changes: 2 additions & 2 deletions src/auth/ejabberd_auth.erl
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ remove_user(#jid{luser = LUser, lserver = LServer}) ->
host_type => HostType,
lserver => LServer,
element => undefined }),
mongoose_hooks:remove_user(LServer, Acc, LUser),
mongoose_hooks:remove_user(Acc, LServer, LUser),
ok;
Error ->
?LOG_ERROR(#{what => backend_disallows_user_removal,
Expand All @@ -390,7 +390,7 @@ entropy(IOList) ->
%%% Internal functions
%%%----------------------------------------------------------------------
%% Return the list of authenticated modules for a given domain
%% TODO: rework is_anonymous_user/1 at ejabberd_users module,
%% TODO: rework is_anonymous_user/1 at mongoose_users module,
%% so there is no need for exporting auth_modules/1 function.
%% after that completely get rid of this interface, we should
%% use auth_modules_for_host_type/1 function instead.
Expand Down
4 changes: 2 additions & 2 deletions src/ejabberd_app.erl
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ start(normal, _Args) ->
%% but some outgoing_pools should be started only with ejabberd_sup already running
ejabberd_sm:start(),
ejabberd_rdbms:start(),
lists:foreach(fun ejabberd_users:start/1, ?MYHOSTS),
lists:foreach(fun mongoose_users:start/1, ?ALL_HOST_TYPES),
ejabberd_auth:start(),
mongoose_cluster_id:start(),
start_services(),
Expand All @@ -90,7 +90,7 @@ prep_stop(State) ->
stop_services(),
mongoose_subhosts:stop(),
broadcast_c2s_shutdown(),
lists:foreach(fun ejabberd_users:stop/1, ?MYHOSTS),
lists:foreach(fun mongoose_users:stop/1, ?ALL_HOST_TYPES),
mongoose_wpool:stop(),
mongoose_metrics:remove_all_metrics(),
State.
Expand Down
213 changes: 0 additions & 213 deletions src/ejabberd_users.erl

This file was deleted.

9 changes: 5 additions & 4 deletions src/event_pusher/mod_event_pusher_push_plugin_defaults.erl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
[mod_event_pusher_push:publish_service()].
should_publish(Acc, #chat_event{to = To}, Services) ->
PublishedServices = mongoose_acc:get(event_pusher, published_services, [], Acc),
case should_publish(To) of
case should_publish(Acc, To) of
true -> Services -- PublishedServices;
false -> []
end;
Expand Down Expand Up @@ -77,9 +77,10 @@ publish_notification(Acc, _, Payload, Services) ->
%% local functions
%%--------------------------------------------------------------------

-spec should_publish(To :: jid:jid()) -> boolean().
should_publish(#jid{} = To) ->
try ejabberd_users:does_user_exist(To) of
-spec should_publish(Acc :: mongoose_acc:t(), To :: jid:jid()) -> boolean().
should_publish(Acc, #jid{} = To) ->
HostType = mongoose_acc:host_type(Acc),
try mongoose_users:does_user_exist(HostType, To) of
false ->
false;
true ->
Expand Down
17 changes: 10 additions & 7 deletions src/inbox/mod_inbox.erl
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ forward_messages(Acc, List, QueryId, To) when is_list(List) ->
-spec send_message(mongoose_acc:t(), jid:jid(), exml:element()) -> mongoose_acc:t().
send_message(Acc, To = #jid{lserver = LServer}, Msg) ->
BareTo = jid:to_bare(To),
{ok, HostType} = mongoose_domain_api:get_domain_host_type(LServer),
HostType = mongoose_acc:host_type(Acc),
NewAcc0 = mongoose_acc:new(#{location => ?LOCATION,
host_type => HostType,
lserver => LServer,
Expand Down Expand Up @@ -287,21 +287,24 @@ remove_domain(Acc, HostType, Domain) ->
Msg :: exml:element(),
Dir :: outgoing | incoming) -> ok | {ok, integer()}.
maybe_process_message(Acc, Host, From, To, Msg, Dir) ->
case should_be_stored_in_inbox(Msg) andalso inbox_owner_exists(From, To, Dir) of
case should_be_stored_in_inbox(Msg) andalso inbox_owner_exists(Acc, From, To, Dir) of
true ->
Type = get_message_type(Msg),
maybe_process_acceptable_message(Host, From, To, Msg, Acc, Dir, Type);
false ->
ok
end.

-spec inbox_owner_exists(From :: jid:jid(),
-spec inbox_owner_exists(Acc :: mongoose_acc:t(),
From :: jid:jid(),
To :: jid:jid(),
Dir :: outgoing | incoming) -> boolean().
inbox_owner_exists(From, _To, outgoing) ->
ejabberd_users:does_user_exist(From);
inbox_owner_exists(_From, To, incoming) ->
ejabberd_users:does_user_exist(To).
inbox_owner_exists(Acc, From, _To, outgoing) ->
HostType = mongoose_acc:host_type(Acc),
mongoose_users:does_user_exist(HostType, From);
inbox_owner_exists(Acc, _From, To, incoming) ->
HostType = mongoose_acc:host_type(Acc),
mongoose_users:does_user_exist(HostType, To).

maybe_process_acceptable_message(Host, From, To, Msg, Acc, Dir, one2one) ->
process_message(Host, From, To, Msg, Acc, Dir, one2one);
Expand Down
3 changes: 2 additions & 1 deletion src/mam/mod_mam.erl
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,9 @@ filter_packet(drop) ->
drop;
filter_packet({From, To = #jid{lserver = LServer}, Acc1, Packet}) ->
?LOG_DEBUG(#{what => mam_user_receive_packet, acc => Acc1}),
HostType = mongoose_acc:host_type(Acc1),
{AmpEvent, PacketAfterArchive, Acc3} =
case ejabberd_users:does_user_exist(To) of
case mongoose_users:does_user_exist(HostType, To) of
false ->
{mam_failed, Packet, Acc1};
true ->
Expand Down
Loading

0 comments on commit 2a0d26a

Please sign in to comment.