1: -module(domain_removal_SUITE). 2: 3: -compile([export_all, nowarn_export_all]). 4: 5: -import(distributed_helper, [mim/0, rpc/4, subhost_pattern/1]). 6: -import(domain_helper, [host_type/0, domain_to_host_type/2, domain/0]). 7: -import(config_parser_helper, [mod_config/2]). 8: 9: -include("mam_helper.hrl"). 10: -include_lib("eunit/include/eunit.hrl"). 11: -include_lib("exml/include/exml_stream.hrl"). 12: -include_lib("jid/include/jid.hrl"). 13: -include_lib("common_test/include/ct.hrl"). 14: 15: all() -> 16: [ 17: {group, auth_removal}, 18: {group, cache_removal}, 19: {group, mam_removal}, 20: {group, mam_removal_incremental}, 21: {group, inbox_removal}, 22: {group, inbox_removal_incremental}, 23: {group, muc_light_removal}, 24: {group, muc_removal}, 25: {group, private_removal}, 26: {group, roster_removal}, 27: {group, offline_removal}, 28: {group, markers_removal}, 29: {group, vcard_removal}, 30: {group, last_removal}, 31: {group, removal_failures} 32: ]. 33: 34: groups() -> 35: [ 36: {auth_removal, [], [auth_removal]}, 37: {cache_removal, [], [cache_removal]}, 38: {mam_removal, [], [mam_pm_removal, 39: mam_muc_removal]}, 40: {mam_removal_incremental, [], [mam_pm_removal, 41: mam_muc_removal]}, 42: {inbox_removal, [], [inbox_removal]}, 43: {inbox_removal_incremental, [], [inbox_removal]}, 44: {muc_light_removal, [], [muc_light_removal, 45: muc_light_blocking_removal]}, 46: {muc_removal, [], [muc_removal]}, 47: {private_removal, [], [private_removal]}, 48: {roster_removal, [], [roster_removal]}, 49: {offline_removal, [], [offline_removal]}, 50: {markers_removal, [], [markers_removal]}, 51: {vcard_removal, [], [vcard_removal]}, 52: {last_removal, [], [last_removal]}, 53: {removal_failures, [], [removal_stops_if_handler_fails]} 54: ]. 55: 56: %%%=================================================================== 57: %%% Overall setup/teardown 58: %%%=================================================================== 59: init_per_suite(Config) -> 60: escalus:init_per_suite(Config). 61: 62: end_per_suite(Config) -> 63: escalus_fresh:clean(), 64: escalus:end_per_suite(Config). 65: 66: %%%=================================================================== 67: %%% Group specific setup/teardown 68: %%%=================================================================== 69: init_per_group(Group, Config) 70: when Group =:= mam_removal_incremental; Group =:= inbox_removal_incremental -> 71: case rpc(mim(), mongoose_rdbms, db_engine, [host_type()]) of 72: odbc -> {skip, mssql_not_supported_for_incremental_removals}; 73: _ -> do_init_per_group(Group, Config) 74: end; 75: init_per_group(Group, Config) -> 76: do_init_per_group(Group, Config). 77: 78: do_init_per_group(auth_removal = Group, Config) -> 79: case is_internal_or_rdbms() of 80: true -> 81: HostTypes = domain_helper:host_types(), 82: Config2 = dynamic_modules:save_modules(HostTypes, Config), 83: [dynamic_modules:ensure_modules(HostType, group_to_modules(Group)) || 84: HostType <- HostTypes], 85: Config2; 86: false -> 87: {skip, require_internal_or_rdbms} 88: end; 89: do_init_per_group(Group, Config) -> 90: case mongoose_helper:is_rdbms_enabled(host_type()) of 91: true -> 92: HostTypes = domain_helper:host_types(), 93: Config2 = dynamic_modules:save_modules(HostTypes, Config), 94: [dynamic_modules:ensure_modules(HostType, group_to_modules(Group)) || 95: HostType <- HostTypes], 96: Config2; 97: false -> 98: {skip, require_rdbms} 99: end. 100: 101: end_per_group(auth_removal, Config) -> 102: case is_internal_or_rdbms() of 103: true -> 104: dynamic_modules:restore_modules(Config); 105: false -> 106: ok 107: end; 108: end_per_group(_GroupName, Config) -> 109: case mongoose_helper:is_rdbms_enabled(host_type()) of 110: true -> 111: dynamic_modules:restore_modules(Config); 112: false -> 113: ok 114: end, 115: ok. 116: 117: group_to_modules(removal_failures) -> 118: group_to_modules(mam_removal); 119: group_to_modules(auth_removal) -> 120: []; 121: group_to_modules(cache_removal) -> 122: [{mod_cache_users, config_parser_helper:default_mod_config(mod_cache_users)}, 123: {mod_mam, mam_helper:config_opts(#{pm => #{}})}]; 124: group_to_modules(mam_removal) -> 125: MucHost = subhost_pattern(muc_light_helper:muc_host_pattern()), 126: [{mod_mam, mam_helper:config_opts(#{pm => #{}, muc => #{host => MucHost}})}, 127: {mod_muc_light, mod_config(mod_muc_light, #{backend => rdbms})}]; 128: group_to_modules(mam_removal_incremental) -> 129: MucHost = subhost_pattern(muc_light_helper:muc_host_pattern()), 130: [{mod_mam, mam_helper:config_opts(#{delete_domain_limit => 1, pm => #{}, muc => #{host => MucHost}})}, 131: {mod_muc_light, mod_config(mod_muc_light, #{backend => rdbms})}]; 132: group_to_modules(muc_light_removal) -> 133: [{mod_muc_light, mod_config(mod_muc_light, #{backend => rdbms})}]; 134: group_to_modules(muc_removal) -> 135: MucHost = subhost_pattern(muc_helper:muc_host_pattern()), 136: OnlineBackend = ct_helper:get_internal_database(), 137: Opts = #{backend => rdbms, online_backend => OnlineBackend, host => MucHost}, 138: [{mod_muc, muc_helper:make_opts(Opts)}]; 139: group_to_modules(inbox_removal) -> 140: [{mod_inbox, inbox_helper:inbox_opts()}]; 141: group_to_modules(inbox_removal_incremental) -> 142: [{mod_inbox, (inbox_helper:inbox_opts())#{delete_domain_limit => 1}}]; 143: group_to_modules(private_removal) -> 144: [{mod_private, #{iqdisc => one_queue, backend => rdbms}}]; 145: group_to_modules(roster_removal) -> 146: [{mod_roster, mod_config(mod_roster, #{backend => rdbms})}]; 147: group_to_modules(offline_removal) -> 148: [{mod_offline, mod_config(mod_offline, #{backend => rdbms})}]; 149: group_to_modules(markers_removal) -> 150: [{mod_smart_markers, config_parser_helper:default_mod_config(mod_smart_markers)}]; 151: group_to_modules(vcard_removal) -> 152: [{mod_vcard, mod_config(mod_vcard, #{backend => rdbms})}]; 153: group_to_modules(last_removal) -> 154: [{mod_last, mod_config(mod_last, #{backend => rdbms})}]. 155: 156: is_internal_or_rdbms() -> 157: AuthMods = mongoose_helper:auth_modules(), 158: Pred = fun(E) -> E == ejabberd_auth_internal orelse E == ejabberd_auth_rdbms end, 159: lists:any(Pred, AuthMods). 160: 161: %%%=================================================================== 162: %%% Testcase specific setup/teardown 163: %%%=================================================================== 164: 165: init_per_testcase(muc_removal, Config) -> 166: muc_helper:load_muc(), 167: mongoose_helper:ensure_muc_clean(), 168: escalus:init_per_testcase(muc_removal, Config); 169: init_per_testcase(roster_removal, ConfigIn) -> 170: Config = roster_helper:set_versioning(true, true, ConfigIn), 171: escalus:init_per_testcase(roster_removal, Config); 172: init_per_testcase(TestCase, Config) -> 173: escalus:init_per_testcase(TestCase, Config). 174: 175: end_per_testcase(muc_removal, Config) -> 176: mongoose_helper:ensure_muc_clean(), 177: muc_helper:unload_muc(), 178: escalus:end_per_testcase(muc_removal, Config); 179: end_per_testcase(TestCase, Config) -> 180: escalus:end_per_testcase(TestCase, Config). 181: 182: %%%=================================================================== 183: %%% Test Cases 184: %%%=================================================================== 185: 186: auth_removal(Config) -> 187: FreshConfig = escalus_fresh:create_users(Config, [{alice, 1}, {alice_bis, 1}]), 188: AliceSpec = escalus_users:get_userspec(FreshConfig, alice), 189: AliceBisSpec = escalus_users:get_userspec(FreshConfig, alice_bis), 190: connect_and_disconnect(AliceSpec), 191: connect_and_disconnect(AliceBisSpec), 192: ?assertMatch([_Alice], rpc(mim(), ejabberd_auth, get_vh_registered_users, [domain()])), 193: run_remove_domain(), 194: ?assertMatch({error, {connection_step_failed, _, _}}, escalus_connection:start(AliceSpec)), 195: connect_and_disconnect(AliceBisSpec), % different domain - not removed 196: ?assertEqual([], rpc(mim(), ejabberd_auth, get_vh_registered_users, [domain()])). 197: 198: cache_removal(Config) -> 199: FreshConfig = escalus_fresh:create_users(Config, [{alice, 1}, {alice_bis, 1}]), 200: F = fun(Alice, AliceBis) -> 201: escalus:send(Alice, escalus_stanza:chat_to(AliceBis, <<"Hi!">>)), 202: escalus:wait_for_stanza(AliceBis), 203: mam_helper:wait_for_archive_size(Alice, 1), 204: mam_helper:wait_for_archive_size(AliceBis, 1) 205: end, 206: escalus:story(FreshConfig, [{alice, 1}, {alice_bis, 1}], F), 207: %% Storing the message in MAM should have populated the cache for both users 208: ?assertEqual({stop, true}, does_cached_user_exist(FreshConfig, alice)), 209: ?assertEqual({stop, true}, does_cached_user_exist(FreshConfig, alice_bis)), 210: run_remove_domain(), 211: %% Cache removed only for Alice's domain 212: ?assertEqual({ok, false}, does_cached_user_exist(FreshConfig, alice)), 213: ?assertEqual({stop, true}, does_cached_user_exist(FreshConfig, alice_bis)). 214: 215: mam_pm_removal(Config) -> 216: F = fun(Alice, Bob) -> 217: N = 3, 218: [ escalus:send(Alice, escalus_stanza:chat_to(Bob, <<"OH, HAI!">>)) || _ <- lists:seq(1, N) ], 219: escalus:wait_for_stanzas(Bob, N), 220: mam_helper:wait_for_archive_size(Alice, N), 221: mam_helper:wait_for_archive_size(Bob, N), 222: run_remove_domain(), 223: mam_helper:wait_for_archive_size(Alice, 0), 224: mam_helper:wait_for_archive_size(Bob, 0) 225: end, 226: escalus_fresh:story(Config, [{alice, 1}, {bob, 1}], F). 227: 228: mam_muc_removal(Config0) -> 229: F = fun(Config, Alice) -> 230: N = 3, 231: Room = muc_helper:fresh_room_name(), 232: MucHost = muc_light_helper:muc_host(), 233: muc_light_helper:create_room(Room, MucHost, alice, 234: [], Config, muc_light_helper:ver(1)), 235: RoomAddr = <<Room/binary, "@", MucHost/binary>>, 236: [ escalus:send(Alice, escalus_stanza:groupchat_to(RoomAddr, <<"text">>)) || _ <- lists:seq(1, N) ], 237: escalus:wait_for_stanzas(Alice, N), 238: mam_helper:wait_for_room_archive_size(MucHost, Room, N), 239: run_remove_domain(), 240: mam_helper:wait_for_room_archive_size(MucHost, Room, 0) 241: end, 242: escalus_fresh:story_with_config(Config0, [{alice, 1}], F). 243: 244: inbox_removal(Config) -> 245: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 246: escalus:send(Alice, escalus_stanza:chat_to(Bob, <<"OH, HAI!">>)), 247: escalus:wait_for_stanza(Bob), 248: inbox_helper:get_inbox(Alice, #{count => 1}), 249: inbox_helper:get_inbox(Bob, #{count => 1}), 250: run_remove_domain(), 251: inbox_helper:get_inbox(Alice, #{count => 0, unread_messages => 0, active_conversations => 0}), 252: inbox_helper:get_inbox(Bob, #{count => 0, unread_messages => 0, active_conversations => 0}) 253: end). 254: 255: muc_removal(Config0) -> 256: muc_helper:story_with_room(Config0, [{persistent, true}], [{alice, 1}], fun(Config, Alice) -> 257: AliceJid= jid:from_binary(escalus_client:full_jid(Alice)), 258: {_, Domain} = jid:to_lus(AliceJid), 259: MucHost = muc_helper:muc_host(), 260: % Alice joins room and registers nick 261: EnterRoom = muc_helper:stanza_muc_enter_room(?config(room, Config), <<"alice">>), 262: escalus:send(Alice, EnterRoom), 263: escalus:wait_for_stanzas(Alice, 2), 264: muc_helper:set_nick(Alice, <<"alice2">>), 265: % check muc tables 266: ?assertMatch([_], get_muc_rooms(MucHost)), 267: ?assertMatch([_], get_muc_room_aff(Domain)), 268: ?assertMatch({ok, _}, get_muc_registered(MucHost, AliceJid)), 269: % remove domain and check muc tables 270: run_remove_domain(), 271: ?assertMatch([], get_muc_rooms(MucHost)), 272: ?assertMatch([], get_muc_room_aff(Domain)), 273: ?assertMatch({error, not_registered}, get_muc_registered(MucHost, AliceJid)) 274: end). 275: 276: muc_light_removal(Config0) -> 277: F = fun(Config, Alice) -> 278: %% GIVEN a room 279: Room = muc_helper:fresh_room_name(), 280: MucHost = muc_light_helper:muc_host(), 281: RoomAddr = <<Room/binary, "@", MucHost/binary>>, 282: muc_light_helper:create_room(Room, MucHost, alice, 283: [], Config, muc_light_helper:ver(1)), 284: escalus:send(Alice, escalus_stanza:groupchat_to(RoomAddr, <<"text">>)), 285: escalus:wait_for_stanza(Alice), 286: RoomID = select_room_id(host_type(), Room, MucHost), 287: {selected, [_]} = select_affs_by_room_id(host_type(), RoomID), 288: {selected, [_|_]} = select_config_by_room_id(host_type(), RoomID), 289: {ok, _RoomConfig, _AffUsers, _Version} = get_room_info(host_type(), Room, MucHost), 290: %% WHEN domain hook called 291: run_remove_domain(), 292: %% THEN Room info not available 293: {error, not_exists} = get_room_info(host_type(), Room, MucHost), 294: %% THEN Tables are empty 295: {selected, []} = select_affs_by_room_id(host_type(), RoomID), 296: {selected, []} = select_config_by_room_id(host_type(), RoomID) 297: end, 298: escalus_fresh:story_with_config(Config0, [{alice, 1}], F). 299: 300: muc_light_blocking_removal(Config0) -> 301: F = fun(Config, Alice, Bob) -> 302: %% GIVEN a room 303: Room = muc_helper:fresh_room_name(), 304: MucHost = muc_light_helper:muc_host(), 305: muc_light_helper:create_room(Room, MucHost, alice, 306: [], Config, muc_light_helper:ver(1)), 307: block_muclight_user(Bob, Alice), 308: [_] = get_blocking(host_type(), Bob, MucHost), 309: %% WHEN domain hook called 310: run_remove_domain(), 311: [] = get_blocking(host_type(), Bob, MucHost) 312: end, 313: escalus_fresh:story_with_config(Config0, [{alice, 1}, {bob, 1}], F). 314: 315: private_removal(Config) -> 316: escalus:fresh_story(Config, [{alice, 1}], fun(Alice) -> 317: NS = <<"alice:private:ns">>, 318: Tag = <<"my_element">>, 319: %% Alice stores some data in her private storage 320: IqSet = escalus_stanza:private_set(my_banana(NS)), 321: IqGet = escalus_stanza:private_get(NS, Tag), 322: escalus:send_iq_and_wait_for_result(Alice, IqSet), 323: %% Compare results before and after removal 324: Res1 = escalus_client:send_iq_and_wait_for_result(Alice, IqGet), 325: run_remove_domain(), 326: Res2 = escalus_client:send_iq_and_wait_for_result(Alice, IqGet), 327: escalus:assert(is_private_result, Res1), 328: escalus:assert(is_private_result, Res2), 329: Val1 = get_private_data(Res1, Tag, NS), 330: Val2 = get_private_data(Res2, Tag, NS), 331: ?assert_equal_extra(<<"banana">>, Val1, #{stanza => Res1}), 332: ?assert_equal_extra(<<>>, Val2, #{stanza => Res2}) 333: end). 334: 335: offline_removal(Config) -> 336: escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}], fun(FreshConfig, Alice, Bob) -> 337: mongoose_helper:logout_user(FreshConfig, Bob), 338: escalus:send(Alice, escalus_stanza:chat_to(Bob, <<"msgtxt">>)), 339: % wait until message is stored 340: BobJid = jid:from_binary(escalus_client:full_jid(Bob)), 341: {LUser, LServer} = jid:to_lus(BobJid), 342: mongoose_helper:wait_until( 343: fun() -> mongoose_helper:total_offline_messages({LUser, LServer}) end, 1), 344: % check messages in DB 345: ?assertMatch({ok, [_]}, rpc(mim(), mod_offline_rdbms, fetch_messages, [host_type(), BobJid])), 346: run_remove_domain(), 347: ?assertMatch({ok, []}, rpc(mim(), mod_offline_rdbms, fetch_messages, [host_type(), BobJid])) 348: end). 349: 350: markers_removal(Config) -> 351: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 352: Body = <<"Hello Bob!">>, 353: MsgId = escalus_stanza:id(), 354: Msg = escalus_stanza:set_id(escalus_stanza:chat_to(Bob, Body), MsgId), 355: escalus:send(Alice, Msg), 356: escalus:wait_for_stanza(Bob), 357: ChatMarker = escalus_stanza:chat_marker(Alice, <<"displayed">>, MsgId), 358: escalus:send(Bob, ChatMarker), 359: escalus:wait_for_stanza(Alice), 360: mongoose_helper:wait_until( 361: fun() -> 1 =< mongoose_helper:generic_count(mod_smart_markers) end, true), 362: % check messages in DB 363: AliceJid = jid:from_binary(escalus_client:full_jid(Alice)), 364: ?assertMatch([_], rpc(mim(), mod_smart_markers_backend, get_chat_markers, 365: [host_type(), AliceJid, undefined, 0])), 366: run_remove_domain(), 367: ?assertMatch([], rpc(mim(), mod_smart_markers_backend, get_chat_markers, 368: [host_type(), AliceJid, undefined, 0])) 369: end). 370: 371: roster_removal(Config) -> 372: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 373: %% add contact 374: Stanza = escalus_stanza:roster_add_contact(Bob, [<<"friends">>], <<"Bobby">>), 375: escalus:send(Alice, Stanza), 376: Received = escalus:wait_for_stanzas(Alice, 2), 377: escalus:assert_many([is_roster_set, is_iq_result], Received), 378: 379: %% check roster 380: BobJid = escalus_client:short_jid(Bob), 381: Received2 = escalus:send_iq_and_wait_for_result(Alice, escalus_stanza:roster_get()), 382: escalus:assert(is_roster_result, Received2), 383: escalus:assert(roster_contains, [BobJid], Received2), 384: escalus:assert(count_roster_items, [1], Received2), 385: ?assertMatch([_], select_from_roster("rosterusers")), 386: ?assertMatch([_], select_from_roster("rostergroups")), 387: ?assertMatch([_], select_from_roster("roster_version")), 388: 389: %% remove domain and check roster 390: run_remove_domain(), 391: Received3 = escalus:send_iq_and_wait_for_result(Alice, escalus_stanza:roster_get()), 392: escalus:assert(is_roster_result, Received3), 393: escalus:assert(count_roster_items, [0], Received3), 394: ?assertMatch([], select_from_roster("rosterusers")), 395: ?assertMatch([], select_from_roster("rostergroups")), 396: ?assertMatch([], select_from_roster("roster_version")) 397: end). 398: 399: vcard_removal(Config) -> 400: escalus:fresh_story(Config, [{alice, 1}], fun(Client) -> 401: DirJID = <<"vjud.", (domain())/binary>>, 402: {LUser, LServer} = jid:to_lus(jid:from_binary(escalus_client:full_jid(Client))), 403: VCardFields = [{<<"FN">>, <<"Old name">>}], 404: FilterFields = [{<<"fn">>, <<"Old name">>}], 405: DbFilterFields = [{<<"fn">>, [<<"Old name">>]}], 406: %create vcard for alice 407: UpdateResult = escalus:send_and_wait(Client, 408: escalus_stanza:vcard_update(VCardFields)), 409: escalus:assert(is_iq_result, UpdateResult), 410: %check before domain removal 411: RequestResult = escalus:send_and_wait(Client, escalus_stanza:vcard_request()), 412: ?assertMatch(<<"Old name">>, get_vcard_fn(RequestResult)), 413: SearchResult = escalus:send_and_wait(Client, 414: search_vcard_fields(DirJID, FilterFields)), 415: ?assertMatch(<<"1">>, get_vcard_search_query_count(SearchResult)), 416: ?assertMatch({ok, _}, rpc(mim(), mod_vcard_rdbms, get_vcard, 417: [host_type(), LUser, LServer])), 418: ?assertMatch([_], rpc(mim(), mod_vcard_rdbms, search, 419: [host_type(), LServer, DbFilterFields])), 420: %check after domain removal 421: run_remove_domain(), 422: RequestResult2 = escalus:send_and_wait(Client, escalus_stanza:vcard_request()), 423: escalus:assert(is_iq_error, RequestResult2), 424: SearchResult2 = escalus:send_and_wait(Client, 425: search_vcard_fields(DirJID, FilterFields)), 426: ?assertMatch(<<"0">>, get_vcard_search_query_count(SearchResult2)), 427: ?assertMatch({error, _}, rpc(mim(), mod_vcard_rdbms, get_vcard, 428: [host_type(), LUser, LServer])), 429: ?assertMatch([], rpc(mim(), mod_vcard_rdbms, search, 430: [host_type(), LServer, DbFilterFields])) 431: end). 432: 433: last_removal(Config0) -> 434: F = fun(Config2, Alice, Bob) -> 435: escalus_story:make_all_clients_friends([Alice, Bob]), 436: 437: %% Bob logs out with a status 438: Status = escalus_stanza:tags([{<<"status">>, <<"I am a banana!">>}]), 439: Presence = escalus_stanza:presence(<<"unavailable">>, Status), 440: escalus_client:send(Bob, Presence), 441: 442: escalus_client:stop(Config2, Bob), 443: timer:sleep(1024), % more than a second 444: 445: PresUn = escalus_client:wait_for_stanza(Alice), 446: escalus:assert(is_presence_with_type, [<<"unavailable">>], PresUn), 447: 448: %% Alice asks for Bob's last availability 449: BobShortJID = escalus_client:short_jid(Bob), 450: GetLast = escalus_stanza:last_activity(BobShortJID), 451: Stanza = escalus_client:send_iq_and_wait_for_result(Alice, GetLast), 452: 453: %% Alice receives Bob's status and last online time > 0 454: escalus:assert(is_last_result, Stanza), 455: true = (1 =< get_last_activity(Stanza)), 456: <<"I am a banana!">> = get_last_status(Stanza), 457: 458: run_remove_domain(), 459: escalus_client:send(Alice, GetLast), 460: Error = escalus_client:wait_for_stanza(Alice), 461: escalus:assert(is_error, [<<"auth">>, <<"forbidden">>], Error) 462: end, 463: escalus:fresh_story_with_config(Config0, [{alice, 1}, {bob, 1}], F). 464: 465: removal_stops_if_handler_fails(Config0) -> 466: mongoose_helper:inject_module(?MODULE), 467: F = fun(Config, Alice) -> 468: start_domain_removal_hook(), 469: Room = muc_helper:fresh_room_name(), 470: MucHost = muc_light_helper:muc_host(), 471: muc_light_helper:create_room(Room, MucHost, alice, [], Config, muc_light_helper:ver(1)), 472: RoomAddr = <<Room/binary, "@", MucHost/binary>>, 473: escalus:send(Alice, escalus_stanza:groupchat_to(RoomAddr, <<"text">>)), 474: escalus:wait_for_stanza(Alice), 475: mam_helper:wait_for_room_archive_size(MucHost, Room, 1), 476: run_remove_domain(), 477: mam_helper:wait_for_room_archive_size(MucHost, Room, 1), 478: stop_domain_removal_hook(), 479: run_remove_domain(), 480: mam_helper:wait_for_room_archive_size(MucHost, Room, 0) 481: end, 482: escalus_fresh:story_with_config(Config0, [{alice, 1}], F). 483: 484: %% Helpers 485: start_domain_removal_hook() -> 486: rpc(mim(), ?MODULE, rpc_start_domain_removal_hook, [host_type()]). 487: 488: stop_domain_removal_hook() -> 489: rpc(mim(), ?MODULE, rpc_stop_domain_removal_hook, [host_type()]). 490: 491: rpc_start_domain_removal_hook(HostType) -> 492: gen_hook:add_handler(remove_domain, HostType, 493: fun ?MODULE:domain_removal_hook_fn/3, 494: #{}, 30). %% Priority is so that it comes before muclight and mam 495: 496: rpc_stop_domain_removal_hook(HostType) -> 497: gen_hook:delete_handler(remove_domain, HostType, 498: fun ?MODULE:domain_removal_hook_fn/3, 499: #{}, 30). 500: 501: domain_removal_hook_fn(Acc, _Params, _Extra) -> 502: F = fun() -> throw(first_time_needs_to_fail) end, 503: mongoose_domain_api:remove_domain_wrapper(Acc, F, ?MODULE). 504: 505: connect_and_disconnect(Spec) -> 506: {ok, Client, _} = escalus_connection:start(Spec), 507: escalus_connection:stop(Client). 508: 509: does_cached_user_exist(Config, User) -> 510: Jid = #jid{lserver = Domain} = jid:from_binary(escalus_users:get_jid(Config, User)), 511: HostType = domain_to_host_type(mim(), Domain), 512: rpc(mim(), mod_cache_users, does_cached_user_exist, [false, #{jid =>Jid, request_type => stored}, #{host_type => HostType}]). 513: 514: search_vcard_fields(DirJID, Filters) -> 515: escalus_stanza:search_iq(DirJID, escalus_stanza:search_fields(Filters)). 516: 517: get_vcard_fn(Element) -> 518: exml_query:path(Element, [{element, <<"vCard">>}, 519: {element, <<"FN">>}, 520: cdata]). 521: 522: get_vcard_search_query_count(Element) -> 523: exml_query:path(Element, [{element, <<"query">>}, 524: {element, <<"set">>}, 525: {element, <<"count">>}, 526: cdata]). 527: 528: get_muc_registered(MucHost, UserJid) -> 529: rpc(mim(), mod_muc_rdbms, get_nick, [host_type(), MucHost, UserJid]). 530: 531: get_muc_rooms(MucHost) -> 532: {ok, Rooms} = rpc(mim(), mod_muc_rdbms, get_rooms, [host_type(), MucHost]), 533: Rooms. 534: 535: get_muc_room_aff(Domain) -> 536: Query = "SELECT * FROM muc_room_aff WHERE lserver = '" ++ binary_to_list(Domain) ++ "'", 537: {selected, Affs} = rpc(mim(), mongoose_rdbms, sql_query, [host_type(), Query]), 538: Affs. 539: 540: select_from_roster(Table) -> 541: Query = "SELECT * FROM " ++ Table ++ " WHERE server='" ++ binary_to_list(domain()) ++ "'", 542: {selected, Res} = rpc(mim(), mongoose_rdbms, sql_query, [host_type(), Query]), 543: Res. 544: 545: run_remove_domain() -> 546: rpc(mim(), mongoose_hooks, remove_domain, [host_type(), domain()]). 547: 548: get_room_info(HostType, RoomU, RoomS) -> 549: rpc(mim(), mod_muc_light_db_backend, get_info, [HostType, {RoomU, RoomS}]). 550: 551: select_room_id(MainHost, RoomU, RoomS) -> 552: {selected, [{DbRoomID}]} = 553: rpc(mim(), mod_muc_light_db_rdbms, select_room_id, [MainHost, RoomU, RoomS]), 554: rpc(mim(), mongoose_rdbms, result_to_integer, [DbRoomID]). 555: 556: select_affs_by_room_id(MainHost, RoomID) -> 557: rpc(mim(), mod_muc_light_db_rdbms, select_affs_by_room_id, [MainHost, RoomID]). 558: 559: select_config_by_room_id(MainHost, RoomID) -> 560: rpc(mim(), mod_muc_light_db_rdbms, select_config_by_room_id, [MainHost, RoomID]). 561: 562: get_blocking(HostType, User, MUCServer) -> 563: Jid = jid:from_binary(escalus_client:short_jid(User)), 564: {LUser, LServer, _} = jid:to_lower(Jid), 565: rpc(mim(), mod_muc_light_db_rdbms, get_blocking, [HostType, {LUser, LServer}, MUCServer]). 566: 567: block_muclight_user(Bob, Alice) -> 568: %% Bob blocks Alice 569: AliceJIDBin = escalus_client:short_jid(Alice), 570: BlocklistChange = [{user, deny, AliceJIDBin}], 571: escalus:send(Bob, muc_light_helper:stanza_blocking_set(BlocklistChange)), 572: escalus:assert(is_iq_result, escalus:wait_for_stanza(Bob)). 573: 574: my_banana(NS) -> 575: #xmlel{ 576: name = <<"my_element">>, 577: attrs = [{<<"xmlns">>, NS}], 578: children = [#xmlcdata{content = <<"banana">>}]}. 579: 580: get_private_data(Elem, Tag, NS) -> 581: Path = [{element, <<"query">>}, {element_with_ns, Tag, NS}, cdata], 582: exml_query:path(Elem, Path). 583: 584: get_last_activity(Stanza) -> 585: S = exml_query:path(Stanza, [{element, <<"query">>}, {attr, <<"seconds">>}]), 586: list_to_integer(binary_to_list(S)). 587: 588: get_last_status(Stanza) -> 589: exml_query:path(Stanza, [{element, <<"query">>}, cdata]).