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