Skip to content

Commit

Permalink
Merge pull request #3291 from esl/domain-removal-mod-roster
Browse files Browse the repository at this point in the history
Implement domain removal in mod_roster
  • Loading branch information
vkatsuba authored Sep 23, 2021
2 parents 9b135ff + 379b5f9 commit a75e7d5
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 30 deletions.
61 changes: 57 additions & 4 deletions big_tests/tests/domain_removal_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
inbox_removal/1,
muc_light_removal/1,
muc_light_blocking_removal/1,
private_removal/1]).
private_removal/1,
roster_removal/1]).

-import(distributed_helper, [mim/0, rpc/4, subhost_pattern/1]).
-import(domain_helper, [host_type/0, domain/0]).
Expand All @@ -30,7 +31,8 @@ all() ->
[{group, mam_removal},
{group, inbox_removal},
{group, muc_light_removal},
{group, private_removal}].
{group, private_removal},
{group, roster_removal}].

groups() ->
[
Expand All @@ -39,7 +41,8 @@ groups() ->
{inbox_removal, [], [inbox_removal]},
{muc_light_removal, [], [muc_light_removal,
muc_light_blocking_removal]},
{private_removal, [], [private_removal]}
{private_removal, [], [private_removal]},
{roster_removal, [], [roster_removal]}
].

%%%===================================================================
Expand Down Expand Up @@ -84,15 +87,23 @@ group_to_modules(muc_light_removal) ->
group_to_modules(inbox_removal) ->
[{mod_inbox, []}];
group_to_modules(private_removal) ->
[{mod_private, [{backend, rdbms}]}].
[{mod_private, [{backend, rdbms}]}];
group_to_modules(roster_removal) ->
[{mod_roster, [{backend, rdbms}]}].

%%%===================================================================
%%% Testcase specific setup/teardown
%%%===================================================================

init_per_testcase(roster_removal, ConfigIn) ->
Config = roster_helper:set_versioning(true, true, ConfigIn),
escalus:init_per_testcase(roster_removal, Config);
init_per_testcase(TestCase, Config) ->
escalus:init_per_testcase(TestCase, Config).

end_per_testcase(roster_removal, Config) ->
roster_helper:restore_versioning(Config),
escalus:end_per_testcase(roster_removal, Config);
end_per_testcase(TestCase, Config) ->
escalus:end_per_testcase(TestCase, Config).

Expand Down Expand Up @@ -197,6 +208,48 @@ private_removal(Config) ->
?assert_equal_extra(<<>>, Val2, #{stanza => Res2})
end).

roster_removal(Config) ->
escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
%% add contact
Stanza = escalus_stanza:roster_add_contact(Bob, [<<"friends">>], <<"Bobby">>),
escalus:send(Alice, Stanza),
Received = escalus:wait_for_stanzas(Alice, 2),
escalus:assert_many([is_roster_set, is_iq_result], Received),

%% check roster
BobJid = escalus_client:short_jid(Bob),
Received2 = escalus:send_iq_and_wait_for_result(Alice, escalus_stanza:roster_get()),
escalus:assert(is_roster_result, Received2),
escalus:assert(roster_contains, [BobJid], Received2),
escalus:assert(count_roster_items, [1], Received2),

{selected, [_]} = select_rosterusers(host_type(), domain()),
{selected, [_]} = select_rostergroups(host_type(), domain()),
{selected, [_]} = select_roster_version(host_type(), domain()),

%% remove domain and check roster
run_remove_domain(),
Received3 = escalus:send_iq_and_wait_for_result(Alice, escalus_stanza:roster_get()),
escalus:assert(is_roster_result, Received3),
escalus:assert(count_roster_items, [0], Received3),

{selected, []} = select_rosterusers(host_type(), domain()),
{selected, []} = select_rostergroups(host_type(), domain()),
{selected, []} = select_roster_version(host_type(), domain())
end).

select_rosterusers(HostType, Domain) ->
Query = "SELECT * FROM rosterusers WHERE server='" ++ binary_to_list(Domain) ++ "'",
rpc(mim(), mongoose_rdbms, sql_query, [HostType, Query]).

select_rostergroups(HostType, Domain) ->
Query = "SELECT * FROM rostergroups WHERE server='" ++ binary_to_list(Domain) ++ "'",
rpc(mim(), mongoose_rdbms, sql_query, [HostType, Query]).

select_roster_version(HostType, Domain) ->
Query = "SELECT * FROM roster_version WHERE server='" ++ binary_to_list(Domain) ++ "'",
rpc(mim(), mongoose_rdbms, sql_query, [HostType, Query]).

run_remove_domain() ->
rpc(mim(), mongoose_hooks, remove_domain, [host_type(), domain()]).

Expand Down
19 changes: 2 additions & 17 deletions big_tests/tests/presence_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

-import(domain_helper, [host_type/0]).

-import(roster_helper, [set_versioning/3, restore_versioning/1]).

%%--------------------------------------------------------------------
%% Suite configuration
%%--------------------------------------------------------------------
Expand Down Expand Up @@ -733,23 +735,6 @@ remove_roster(Config, UserSpec) ->
end
end.

set_versioning(Versioning, VersionStore, Config) ->
RosterVersioning = rpc(mim(), gen_mod, get_module_opt,
[host_type(), mod_roster, versioning, false]),
RosterVersionOnDb = rpc(mim(), gen_mod, get_module_opt,
[host_type(), mod_roster, store_current_id, false]),
rpc(mim(), gen_mod, set_module_opt, [host_type(), mod_roster, versioning, Versioning]),
rpc(mim(), gen_mod, set_module_opt, [host_type(), mod_roster, store_current_id, VersionStore]),
[{versioning, RosterVersioning},
{store_current_id, RosterVersionOnDb} | Config].

restore_versioning(Config) ->
RosterVersioning = proplists:get_value(versioning, Config),
RosterVersionOnDb = proplists:get_value(store_current_id, Config),
rpc(mim(), gen_mod, get_module_opt, [host_type(), mod_roster, versioning, RosterVersioning]),
rpc(mim(), gen_mod, get_module_opt, [host_type(), mod_roster, store_current_id, RosterVersionOnDb]).


check_roster_count(User, ExpectedCount) ->
% the user sends get_roster iq
escalus_client:send(User, escalus_stanza:roster_get()),
Expand Down
23 changes: 23 additions & 0 deletions big_tests/tests/roster_helper.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-module(roster_helper).
-export([set_versioning/3, restore_versioning/1]).

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

-spec set_versioning(boolean(), boolean(), escalus_config:config()) -> escalus_config:config().
set_versioning(Versioning, VersionStore, Config) ->
RosterVersioning = rpc(mim(), gen_mod, get_module_opt,
[host_type(), mod_roster, versioning, false]),
RosterVersionOnDb = rpc(mim(), gen_mod, get_module_opt,
[host_type(), mod_roster, store_current_id, false]),
rpc(mim(), gen_mod, set_module_opt, [host_type(), mod_roster, versioning, Versioning]),
rpc(mim(), gen_mod, set_module_opt, [host_type(), mod_roster, store_current_id, VersionStore]),
[{versioning, RosterVersioning},
{store_current_id, RosterVersionOnDb} | Config].

-spec restore_versioning(escalus_config:config()) -> escalus_config:config().
restore_versioning(Config) ->
RosterVersioning = proplists:get_value(versioning, Config),
RosterVersionOnDb = proplists:get_value(store_current_id, Config),
rpc(mim(), gen_mod, get_module_opt, [host_type(), mod_roster, versioning, RosterVersioning]),
rpc(mim(), gen_mod, get_module_opt, [host_type(), mod_roster, store_current_id, RosterVersionOnDb]).
8 changes: 2 additions & 6 deletions src/auth/mongoose_gen_auth.erl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

-ignore_xref([behaviour_info/1]).

-import(backend_module, [is_exported/3]).

%% Mandatory callbacks

-callback start(HostType :: mongooseim:host_type()) -> ok.
Expand Down Expand Up @@ -232,9 +234,3 @@ check_password(Mod, HostType, LUser, LServer, Password, Digest, DigestGen) ->
true -> Mod:check_password(HostType, LUser, LServer, Password, Digest, DigestGen);
false -> false
end.

%% Internal functions

is_exported(Mod, F, Arity) ->
code:ensure_loaded(Mod),
erlang:function_exported(Mod, F, Arity).
8 changes: 7 additions & 1 deletion src/backend_module.erl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
-author('[email protected]').
-author('[email protected]').

-export([create/2, backend_module/2, create/3]).
-export([create/2, backend_module/2, create/3, is_exported/3]).

-ignore_xref([create/2, backend_module/2, behaviour_info/1]).

Expand Down Expand Up @@ -56,6 +56,12 @@ create(Module, Backend, TrackedFuns) ->
{ok, ProxyModule}
end.

-spec is_exported(Module :: module(), Function :: atom(),
Arity :: integer()) -> boolean().
is_exported(Module, Function, Arity) ->
code:ensure_loaded(Module),
erlang:function_exported(Module, Function, Arity).

%% Internal functions

-spec proxy_module(Module :: module()) -> module().
Expand Down
28 changes: 27 additions & 1 deletion src/mod_roster.erl
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
get_subscription_lists/2,
get_jid_info/4,
remove_user/3,
remove_domain/3,
get_versioning_feature/2,
get_personal_data/3
]).
Expand All @@ -79,6 +80,7 @@
{?MOD_ROSTER_BACKEND, get_subscription_lists, 3},
{?MOD_ROSTER_BACKEND, read_roster_version, 3},
{?MOD_ROSTER_BACKEND, remove_user_t, 3},
{?MOD_ROSTER_BACKEND, remove_domain_t, 2},
{?MOD_ROSTER_BACKEND, roster_subscribe_t, 2},
{?MOD_ROSTER_BACKEND, init, 2},
{?MOD_ROSTER_BACKEND, transaction, 2},
Expand All @@ -87,7 +89,7 @@
behaviour_info/1, get_jid_info/4, get_personal_data/3, get_subscription_lists/2,
get_user_roster/2, get_user_rosters_length/2, get_versioning_feature/2,
in_subscription/5, item_to_xml/1, out_subscription/4, process_subscription_t/6,
remove_user/3, transaction/2
remove_user/3, remove_domain/3, transaction/2
]).

-include("mongoose.hrl").
Expand Down Expand Up @@ -143,6 +145,10 @@

-callback remove_user_t(mongooseim:host_type(), jid:luser(), jid:lserver()) -> ok.

-callback remove_domain_t(mongooseim:host_type(), jid:lserver()) -> ok.

-optional_callbacks([remove_domain_t/2]).

%%--------------------------------------------------------------------
%% gdpr callback
%%--------------------------------------------------------------------
Expand Down Expand Up @@ -224,6 +230,7 @@ hooks(HostType) ->
{roster_get_subscription_lists, HostType, ?MODULE, get_subscription_lists, 50},
{roster_get_jid_info, HostType, ?MODULE, get_jid_info, 50},
{remove_user, HostType, ?MODULE, remove_user, 50},
{remove_domain, HostType, ?MODULE, remove_domain, 50},
{anonymous_purge_hook, HostType, ?MODULE, remove_user, 50},
{roster_get_versioning_feature, HostType, ?MODULE, get_versioning_feature, 50},
{get_personal_data, HostType, ?MODULE, get_personal_data, 50}].
Expand Down Expand Up @@ -878,6 +885,25 @@ send_presence_type(From, To, Type) ->

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-spec remove_domain(mongoose_hooks:simple_acc(),
mongooseim:host_type(), jid:lserver()) ->
mongoose_hooks:simple_acc().
remove_domain(Acc, HostType, Domain) ->
case backend_module:is_exported(mod_roster_backend, remove_domain_t, 2) of
true ->
F = fun() -> mod_roster_backend:remove_domain_t(HostType, Domain) end,
case transaction(HostType, F) of
{atomic, ok} ->
ok;
Result ->
?LOG_ERROR(#{what => remove_domain_transaction_failed,
reason => Result})
end;
false ->
ok
end,
Acc.

-spec set_items(mongooseim:host_type(), jid:jid(), exml:element()) -> ok | {error, any()}.
set_items(HostType, #jid{luser = LUser, lserver = LServer}, SubEl) ->
F = fun() -> set_items_t(HostType, LUser, LServer, SubEl) end,
Expand Down
16 changes: 15 additions & 1 deletion src/mod_roster_rdbms.erl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
roster_subscribe_t/2,
update_roster_t/2,
del_roster_t/4,
remove_user_t/3]).
remove_user_t/3,
remove_domain_t/2]).

%% mod_roster backend API

Expand Down Expand Up @@ -114,6 +115,13 @@ remove_user_t(HostType, LUser, LServer) ->
mongoose_rdbms:execute_successfully(HostType, roster_group_delete, [LServer, LUser]),
ok.

-spec remove_domain_t(mongooseim:host_type(), jid:lserver()) -> ok.
remove_domain_t(HostType, Domain) ->
mongoose_rdbms:execute_successfully(HostType, rosterusers_remove_domain, [Domain]),
mongoose_rdbms:execute_successfully(HostType, rostergroups_remove_domain, [Domain]),
mongoose_rdbms:execute_successfully(HostType, roster_version_remove_domain, [Domain]),
ok.

%% Query preparation

prepare_queries(HostType) ->
Expand Down Expand Up @@ -144,6 +152,12 @@ prepare_queries(HostType) ->
mongoose_rdbms:prepare(roster_group_delete_by_jid, rostergroups, [server, username, jid],
<<"DELETE FROM rostergroups"
" WHERE server = ? AND username = ? AND jid = ?">>),
mongoose_rdbms:prepare(rosterusers_remove_domain, rosterusers, [server],
<<"DELETE FROM rosterusers WHERE server = ?">>),
mongoose_rdbms:prepare(rostergroups_remove_domain, rostergroups, [server],
<<"DELETE FROM rostergroups WHERE server = ?">>),
mongoose_rdbms:prepare(roster_version_remove_domain, roster_version, [server],
<<"DELETE FROM roster_version WHERE server = ?">>),
prepare_roster_upsert(HostType),
prepare_version_upsert(HostType),
ok.
Expand Down

0 comments on commit a75e7d5

Please sign in to comment.