1: -module(graphql_muc_light_SUITE).
    2: 
    3: -compile([export_all, nowarn_export_all]).
    4: 
    5: -import(common_helper, [unprep/1]).
    6: -import(distributed_helper, [mim/0, require_rpc_nodes/1, rpc/4, subhost_pattern/1]).
    7: -import(graphql_helper, [execute_user_command/5, execute_command/4, get_listener_port/1,
    8:                          get_listener_config/1, get_ok_value/2, get_err_msg/1,
    9:                          get_coercion_err_msg/1, make_creds/1, get_unauthorized/1,
   10:                          get_err_code/1, get_not_loaded/1]).
   11: 
   12: -import(config_parser_helper, [mod_config/2]).
   13: 
   14: -include_lib("common_test/include/ct.hrl").
   15: -include_lib("jid/include/jid.hrl").
   16: -include_lib("eunit/include/eunit.hrl").
   17: -include_lib("exml/include/exml.hrl").
   18: 
   19: -define(UNKNOWN_DOMAIN, <<"not-existing-domain">>).
   20: -define(UNKNOWN, <<"not-existing">>).
   21: 
   22: %% GraphQL Paths
   23: -define(CREATE_ROOM_PATH, [data, muc_light, createRoom]).
   24: -define(CHANGE_CONFIG_PATH, [data, muc_light, changeRoomConfiguration]).
   25: -define(INVITE_USER_PATH, [data, muc_light, inviteUser]).
   26: -define(KICK_USER_PATH, [data, muc_light, kickUser]).
   27: -define(DELETE_ROOM_PATH, [data, muc_light, deleteRoom]).
   28: -define(SEND_MESSAGE_PATH, [data, muc_light, sendMessageToRoom]).
   29: -define(GET_MESSAGES_PATH, [data, muc_light, getRoomMessages]).
   30: -define(LIST_USER_ROOMS_PATH, [data, muc_light, listUserRooms]).
   31: -define(USER_LIST_ROOMS_PATH, [data, muc_light, listRooms]).
   32: -define(LIST_ROOM_USERS_PATH, [data, muc_light, listRoomUsers]).
   33: -define(GET_ROOM_CONFIG_PATH, [data, muc_light, getRoomConfig]).
   34: -define(GET_BLOCKING_LIST_PATH, [data, muc_light, getBlockingList]).
   35: -define(SET_BLOCKING_LIST_PATH, [data, muc_light, setBlockingList]).
   36: 
   37: suite() ->
   38:     require_rpc_nodes([mim]) ++ escalus:suite().
   39: 
   40: all() ->
   41:     [{group, user},
   42:      {group, admin_http},
   43:      {group, admin_cli},
   44:      {group, domain_admin}].
   45: 
   46: groups() ->
   47:     [{user, [], user_groups()},
   48:      {admin_http, [], admin_groups()},
   49:      {admin_cli, [], admin_groups()},
   50:      {domain_admin, domain_admin_groups()},
   51:      {user_muc_light, [parallel], user_muc_light_tests()},
   52:      {user_muc_light_with_mam, [parallel], user_muc_light_with_mam_tests()},
   53:      {user_muc_light_not_configured, [], user_muc_light_not_configured_tests()},
   54:      {admin_muc_light, [], admin_muc_light_tests()},
   55:      {admin_muc_light_with_mam, [], admin_muc_light_with_mam_tests()},
   56:      {domain_admin_muc_light, [], domain_admin_muc_light_tests()},
   57:      {domain_admin_muc_light_with_mam, [], domain_admin_muc_light_with_mam_tests()},
   58:      {admin_muc_light_not_configured, [], admin_muc_light_not_configured_tests()}].
   59: 
   60: user_groups() ->
   61:     [{group, user_muc_light},
   62:      {group, user_muc_light_with_mam},
   63:      {group, user_muc_light_not_configured}].
   64: 
   65: admin_groups() ->
   66:     [{group, admin_muc_light},
   67:      {group, admin_muc_light_with_mam},
   68:      {group, admin_muc_light_not_configured}].
   69: 
   70: domain_admin_groups() ->
   71:     [{group, domain_admin_muc_light},
   72:      {group, domain_admin_muc_light_with_mam}].
   73: 
   74: user_muc_light_tests() ->
   75:     [user_create_room,
   76:      user_create_room_with_unprepped_domain,
   77:      user_create_room_with_bad_config,
   78:      user_create_room_with_custom_fields,
   79:      user_create_identified_room,
   80:      user_create_room_with_unprepped_id,
   81:      user_change_room_config,
   82:      user_change_room_config_errors,
   83:      user_invite_user,
   84:      user_invite_user_errors,
   85:      user_delete_room,
   86:      user_kick_user,
   87:      user_send_message_to_room,
   88:      user_send_message_to_room_errors,
   89:      user_get_room_messages_muc_light_or_mam_not_configured,
   90:      user_list_rooms,
   91:      user_list_room_users,
   92:      user_get_room_config,
   93:      user_blocking_list
   94:     ].
   95: 
   96: user_muc_light_with_mam_tests() ->
   97:     [user_get_room_messages,
   98:      user_shouldnt_store_messages_in_muc].
   99: 
  100: user_muc_light_not_configured_tests() ->
  101:     [user_create_room_muc_light_not_configured,
  102:      user_change_room_config_muc_light_not_configured,
  103:      user_invite_user_muc_light_not_configured,
  104:      user_delete_room_muc_light_not_configured,
  105:      user_kick_user_muc_light_not_configured,
  106:      user_send_message_to_room_muc_light_not_configured,
  107:      user_get_room_messages_muc_light_or_mam_not_configured,
  108:      user_list_rooms_muc_light_not_configured,
  109:      user_list_room_users_muc_light_not_configured,
  110:      user_get_room_config_muc_light_not_configured,
  111:      user_blocking_list_muc_light_not_configured].
  112: 
  113: admin_muc_light_tests() ->
  114:     [admin_create_room,
  115:      admin_create_room_non_existent_domain,
  116:      admin_create_room_with_unprepped_domain,
  117:      admin_create_room_with_custom_fields,
  118:      admin_create_identified_room,
  119:      admin_create_identified_room_non_existent_domain,
  120:      admin_create_room_with_unprepped_id,
  121:      admin_change_room_config,
  122:      admin_change_room_config_with_custom_fields,
  123:      admin_change_room_config_errors,
  124:      admin_change_room_config_non_existent_domain,
  125:      admin_invite_user,
  126:      admin_invite_user_errors,
  127:      admin_delete_room,
  128:      admin_delete_room_non_existent_domain,
  129:      admin_kick_user,
  130:      admin_send_message_to_room,
  131:      admin_send_message_to_room_errors,
  132:      admin_get_room_messages_muc_light_or_mam_not_configured,
  133:      admin_list_user_rooms,
  134:      admin_list_user_rooms_non_existent_domain,
  135:      admin_list_room_users,
  136:      admin_list_room_users_non_existent_domain,
  137:      admin_get_room_config,
  138:      admin_get_room_config_non_existent_domain,
  139:      admin_blocking_list,
  140:      admin_blocking_list_null,
  141:      admin_blocking_list_errors
  142:     ].
  143: 
  144: admin_muc_light_with_mam_tests() ->
  145:     [admin_get_room_messages,
  146:      admin_get_room_messages_non_existent_domain].
  147: 
  148: domain_admin_muc_light_tests() ->
  149:     [admin_create_room,
  150:      admin_create_room_with_unprepped_domain,
  151:      admin_create_room_with_custom_fields,
  152:      domain_admin_create_room_no_permission,
  153:      admin_create_identified_room,
  154:      admin_create_room_with_unprepped_id,
  155:      domain_admin_create_identified_room_no_permission,
  156:      admin_change_room_config,
  157:      admin_change_room_config_with_custom_fields,
  158:      admin_change_room_config_errors,
  159:      domain_admin_change_room_config_no_permission,
  160:      admin_invite_user,
  161:      admin_invite_user_errors,
  162:      domain_admin_invite_user_no_permission,
  163:      admin_delete_room,
  164:      domain_admin_delete_room_no_permission,
  165:      admin_kick_user,
  166:      domain_admin_kick_user_no_permission,
  167:      admin_send_message_to_room,
  168:      admin_send_message_to_room_errors,
  169:      domain_admin_send_message_to_room_no_permission,
  170:      admin_get_room_messages_muc_light_or_mam_not_configured,
  171:      admin_list_user_rooms,
  172:      domain_admin_list_user_rooms_no_permission,
  173:      admin_list_room_users,
  174:      domain_admin_list_room_users_no_permission,
  175:      admin_get_room_config,
  176:      domain_admin_get_room_config_no_permission,
  177:      admin_blocking_list,
  178:      domain_admin_blocking_list_no_permission
  179:     ].
  180: 
  181: domain_admin_muc_light_with_mam_tests() ->
  182:     [admin_get_room_messages,
  183:      domain_admin_get_room_messages_no_permission].
  184: 
  185: admin_muc_light_not_configured_tests() ->
  186:     [admin_create_room_muc_light_not_configured,
  187:      admin_change_room_config_muc_light_not_configured,
  188:      admin_invite_user_muc_light_not_configured,
  189:      admin_delete_room_muc_light_not_configured,
  190:      admin_kick_user_muc_light_not_configured,
  191:      admin_send_message_to_room_muc_light_not_configured,
  192:      admin_get_room_messages_muc_light_or_mam_not_configured,
  193:      admin_list_user_rooms_muc_light_not_configured,
  194:      admin_list_room_users_muc_light_not_configured,
  195:      admin_get_room_config_muc_light_not_configured,
  196:      admin_blocking_list_muc_light_not_configured].
  197: 
  198: init_per_suite(Config) ->
  199:     HostType = domain_helper:host_type(),
  200:     SecondaryHostType = domain_helper:secondary_host_type(),
  201:     Config1 = dynamic_modules:save_modules(HostType, Config),
  202:     Config2 = dynamic_modules:save_modules(SecondaryHostType, Config1),
  203:     Config3 = ejabberd_node_utils:init(mim(), Config2),
  204:     escalus:init_per_suite(Config3).
  205: 
  206: end_per_suite(Config) ->
  207:     escalus_fresh:clean(),
  208:     dynamic_modules:restore_modules(Config),
  209:     escalus:end_per_suite(Config).
  210: 
  211: required_modules(_) ->
  212:     Backend = mongoose_helper:mnesia_or_rdbms_backend(),
  213:     MucLightOpts = mod_config(mod_muc_light, #{backend => Backend,
  214:                                                rooms_in_rosters => true,
  215:                                                config_schema => custom_schema()}),
  216:     [{mod_muc_light, MucLightOpts}].
  217: 
  218: custom_schema() ->
  219:     %% Should be sorted
  220:     [{<<"background">>, <<>>, background, binary},
  221:      {<<"music">>, <<>>, music, binary},
  222:      %% Default fields
  223:      {<<"roomname">>, <<>>, roomname, binary},
  224:      {<<"subject">>, <<"Test">>, subject, binary}].
  225: 
  226: init_per_group(admin_http, Config) ->
  227:     graphql_helper:init_admin_handler(Config);
  228: init_per_group(admin_cli, Config) ->
  229:     graphql_helper:init_admin_cli(Config);
  230: init_per_group(domain_admin, Config) ->
  231:     graphql_helper:init_domain_admin_handler(Config);
  232: init_per_group(Group, Config) when Group =:= user_muc_light;
  233:                                    Group =:= admin_muc_light;
  234:                                    Group =:= domain_admin_muc_light ->
  235:     disable_mam(),
  236:     ensure_muc_light_started(Config);
  237: init_per_group(Group, Config) when Group =:= user_muc_light_with_mam;
  238:                                    Group =:= admin_muc_light_with_mam;
  239:                                    Group =:= domain_admin_muc_light_with_mam ->
  240:     case maybe_enable_mam() of
  241:         true ->
  242:             ensure_muc_started(),
  243:             ensure_muc_light_started(Config);
  244:         false ->
  245:             {skip, "No MAM backend available"}
  246:     end;
  247: init_per_group(Group, Config) when Group =:= user_muc_light_not_configured;
  248:                                    Group =:= admin_muc_light_not_configured ->
  249:     maybe_enable_mam(),
  250:     ensure_muc_light_stopped(Config);
  251: init_per_group(user, Config) ->
  252:     graphql_helper:init_user(Config).
  253: 
  254: disable_mam() ->
  255:     dynamic_modules:ensure_modules(domain_helper:host_type(), [{mod_mam, stopped}]).
  256: 
  257: maybe_enable_mam() ->
  258:     case mam_helper:backend() of
  259:         disabled ->
  260:             false;
  261:         Backend ->
  262:             MAMOpts = mam_helper:config_opts(
  263:                         #{backend => Backend,
  264:                           muc => #{host => subhost_pattern(muc_light_helper:muc_host_pattern())},
  265:                           async_writer => #{enabled => false}}),
  266:             dynamic_modules:ensure_modules(domain_helper:host_type(), [{mod_mam, MAMOpts}]),
  267:             true
  268:     end.
  269: 
  270: ensure_muc_light_started(Config) ->
  271:     HostType = domain_helper:host_type(),
  272:     SecondaryHostType = domain_helper:secondary_host_type(),
  273:     dynamic_modules:ensure_modules(HostType, required_modules(suite)),
  274:     dynamic_modules:ensure_modules(SecondaryHostType, required_modules(suite)),
  275:     [{muc_light_host, muc_light_helper:muc_host()},
  276:      {secondary_muc_light_host, <<"muclight.", (domain_helper:secondary_domain())/binary>>}
  277:      | Config].
  278: 
  279: ensure_muc_light_stopped(Config) ->
  280:     HostType = domain_helper:host_type(),
  281:     SecondaryHostType = domain_helper:secondary_host_type(),
  282:     dynamic_modules:ensure_modules(HostType, [{mod_muc_light, stopped}]),
  283:     dynamic_modules:ensure_modules(SecondaryHostType, [{mod_muc_light, stopped}]),
  284:     [{muc_light_host, <<"NON_EXISTING">>} | Config].
  285: 
  286: ensure_muc_started() ->
  287:     muc_helper:load_muc(),
  288:     mongoose_helper:ensure_muc_clean().
  289: 
  290: ensure_muc_stopped() ->
  291:     muc_helper:unload_muc().
  292: 
  293: end_per_group(Group, _Config) when Group =:= user;
  294:                                    Group =:= admin_http;
  295:                                    Group =:= admin_cli;
  296:                                    Group =:= domain_admin ->
  297:     maybe_clear_db(),
  298:     graphql_helper:clean();
  299: end_per_group(Group, _Config) when Group =:= user_muc_light_with_mam;
  300:                                    Group =:= admin_muc_light_with_mam;
  301:                                    Group =:= domain_admin_muc_light_with_mam ->
  302:     maybe_clear_db(),
  303:     ensure_muc_stopped(),
  304:     escalus_fresh:clean();
  305: end_per_group(_Group, _Config) ->
  306:     maybe_clear_db(),
  307:     escalus_fresh:clean().
  308: 
  309: maybe_clear_db() ->
  310:     case mongoose_helper:is_rdbms_enabled(domain_helper:host_type()) of
  311:         true ->
  312:             ok = rpc(mim(), mod_muc_light_db_rdbms, force_clear, []);
  313:         false ->
  314:             ok
  315:     end.
  316: 
  317: init_per_testcase(TC, Config) ->
  318:     rest_helper:maybe_skip_mam_test_cases(TC, [user_get_room_messages,
  319:                                                admin_get_room_messages], Config).
  320: 
  321: end_per_testcase(TC, Config) ->
  322:     escalus:end_per_testcase(TC, Config).
  323: 
  324: %% User test cases
  325: 
  326: user_create_room(Config) ->
  327:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun user_create_room_story/2).
  328: 
  329: user_create_room_story(Config, Alice) ->
  330:     MucServer = ?config(muc_light_host, Config),
  331:     AliceBinLower = escalus_utils:jid_to_lower(escalus_client:short_jid(Alice)),
  332:     Name = <<"first room">>,
  333:     Subject = <<"testing">>,
  334:     Res = user_create_room(Alice, MucServer, Name, Subject, null, Config),
  335:     #{<<"jid">> := JID, <<"name">> := Name, <<"subject">> := Subject,
  336:       <<"participants">> := Participants} = get_ok_value(?CREATE_ROOM_PATH, Res),
  337:     ?assertMatch(#jid{lserver = MucServer}, jid:from_binary(JID)),
  338:     ?assertEqual([#{<<"jid">> => AliceBinLower, <<"affiliation">> => <<"OWNER">>}], Participants),
  339:     % Try with a non-existent domain
  340:     Res2 = user_create_room(Alice, ?UNKNOWN_DOMAIN, Name, Subject, null, Config),
  341:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"not found">>)).
  342: 
  343: user_create_room_with_unprepped_domain(Config) ->
  344:     escalus:fresh_story_with_config(Config, [{alice, 1}],
  345:                                     fun user_create_room_with_unprepped_domain_story/2).
  346: 
  347: user_create_room_with_unprepped_domain_story(Config, Alice) ->
  348:     MucServer = ?config(muc_light_host, Config),
  349:     Name = <<"room with unprepped domain">>,
  350:     Subject = <<"testing">>,
  351:     Res = user_create_room(Alice, unprep(MucServer), Name, Subject, null, Config),
  352:     #{<<"jid">> := JID, <<"name">> := Name, <<"subject">> := Subject} =
  353:         get_ok_value(?CREATE_ROOM_PATH, Res),
  354:     ?assertMatch(#jid{lserver = MucServer}, jid:from_binary_noprep(JID)).
  355: 
  356: user_create_room_with_bad_config(Config) ->
  357:     escalus:fresh_story_with_config(Config, [{alice, 1}],
  358:                                     fun user_create_room_with_bad_config_story/2).
  359: 
  360: user_create_room_with_bad_config_story(Config, Alice) ->
  361:     MucServer = ?config(muc_light_host, Config),
  362:     Name = <<"room with custom fields">>,
  363:     Subject = <<"testing_custom">>,
  364:     Opts = #{<<"badkey">> => <<"badvalue">>},
  365:     Res =  user_create_room_with_options(Alice, MucServer, Name, Subject, null, Opts, Config),
  366:     ?assertMatch({_, _}, binary:match(get_err_msg(Res), <<"Validation failed for key: badkey">>)).
  367: 
  368: user_create_room_with_custom_fields(Config) ->
  369:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun user_create_room_with_custom_fields_story/2).
  370: 
  371: user_create_room_with_custom_fields_story(Config, Alice) ->
  372:     MucServer = ?config(muc_light_host, Config),
  373:     AliceBinLower = escalus_utils:jid_to_lower(escalus_client:short_jid(Alice)),
  374:     Name = <<"room with custom fields">>,
  375:     Subject = <<"testing_custom">>,
  376:     Opts = [#{<<"key">> => <<"background">>, <<"value">> => <<"red">>},
  377:             #{<<"key">> => <<"roomname">>, <<"value">> => Name},
  378:             #{<<"key">> => <<"subject">>, <<"value">> => Subject}],
  379:     Res = user_create_room_with_options(Alice, MucServer, Name, Subject, null,
  380:                                         #{<<"background">> => <<"red">>}, Config),
  381:     #{<<"jid">> := JID, <<"name">> := Name, <<"subject">> := Subject,
  382:       <<"participants">> := Participants, <<"options">> := Opts}
  383:         = get_ok_value(?CREATE_ROOM_PATH, Res),
  384:     ?assertMatch(#jid{lserver = MucServer}, jid:from_binary(JID)),
  385:     ?assertEqual([#{<<"jid">> => AliceBinLower, <<"affiliation">> => <<"OWNER">>}], Participants).
  386: 
  387: user_create_identified_room(Config) ->
  388:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun user_create_identified_room_story/2).
  389: 
  390: user_create_identified_room_story(Config, Alice) ->
  391:     MucServer = ?config(muc_light_host, Config),
  392:     Name = <<"first room">>,
  393:     Subject = <<"testing">>,
  394:     Id = <<"my_user_room">>,
  395:     Res = user_create_room(Alice, MucServer, Name, Subject, Id, Config),
  396:     #{<<"jid">> := JID, <<"name">> := Name, <<"subject">> := Subject} =
  397:         get_ok_value(?CREATE_ROOM_PATH, Res),
  398:     ?assertMatch(#jid{luser = Id, lserver = MucServer}, jid:from_binary(JID)),
  399:     % Create a room with an existing ID
  400:     Res2 = user_create_room(Alice, MucServer, <<"snd room">>, Subject, Id, Config),
  401:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"already exists">>)),
  402:     % Try with a non-existent domain
  403:     Res3 = user_create_room(Alice, ?UNKNOWN_DOMAIN, <<"name">>, Subject, Id, Config),
  404:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res3), <<"not found">>)),
  405:     % Try with an empty string passed as ID
  406:     Res4 = user_create_room(Alice, MucServer, <<"name">>, Subject, <<>>, Config),
  407:     ?assertMatch({_, _}, binary:match(get_coercion_err_msg(Res4), <<"empty_room_name">>)).
  408: 
  409: user_create_room_with_unprepped_id(Config) ->
  410:     escalus:fresh_story_with_config(Config, [{alice, 1}],
  411:                                     fun user_create_room_with_unprepped_id_story/2).
  412: 
  413: user_create_room_with_unprepped_id_story(Config, Alice) ->
  414:     MucServer = ?config(muc_light_host, Config),
  415:     Name = <<"first room">>,
  416:     Subject = <<"testing">>,
  417:     Id = <<"user_room_with_unprepped_id">>,
  418:     Res = user_create_room(Alice, unprep(MucServer), Name, Subject, unprep(Id), Config),
  419:     #{<<"jid">> := JID, <<"name">> := Name, <<"subject">> := Subject} =
  420:         get_ok_value(?CREATE_ROOM_PATH, Res),
  421:     ?assertMatch(#jid{luser = Id, lserver = MucServer}, jid:from_binary_noprep(JID)).
  422: 
  423: user_change_room_config(Config) ->
  424:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun user_change_room_config_story/2).
  425: 
  426: user_change_room_config_story(Config, Alice) ->
  427:     AliceBin = escalus_client:short_jid(Alice),
  428:     MUCServer = ?config(muc_light_host, Config),
  429:     % Create a new room
  430:     {ok, #{jid := RoomJID}} = create_room(MUCServer, <<"ornithology">>, <<"birds">>, AliceBin),
  431:     % Try to change the room configuration
  432:     Name2 = <<"changed room">>,
  433:     Subject2 = <<"not testing">>,
  434:     Res = user_change_room_configuration(Alice, jid:to_binary(RoomJID), Name2, Subject2, Config),
  435:     ?assertMatch(#{<<"name">> := Name2, <<"subject">> := Subject2}, get_ok_value(?CHANGE_CONFIG_PATH, Res)).
  436: 
  437: user_change_room_config_with_custom_fields(Config) ->
  438:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun user_change_room_config_with_custom_fields_story/2).
  439: 
  440: user_change_room_config_with_custom_fields_story(Config, Alice) ->
  441:     AliceBin = escalus_client:short_jid(Alice),
  442:     MUCServer = ?config(muc_light_host, Config),
  443:     % Create a new room
  444:     {ok, #{jid := RoomJID}} = create_room(MUCServer, <<"ornithology">>, <<"birds">>, AliceBin),
  445:     % Try to change the room configuration
  446:     Name2 = <<"changed room">>,
  447:     Subject2 = <<"not testing">>,
  448:     Opts2 = #{<<"music">> => <<"sad">>},
  449:     Res = user_change_room_configuration_with_custom_fields(Alice, jid:to_binary(RoomJID), Name2, Subject2, Config, Opts2),
  450:     Opts3 = [#{<<"key">> => <<"music">>, <<"value">> => <<"sad">>},
  451:              #{<<"key">> => <<"roomname">>, <<"value">> => Name2},
  452:              #{<<"key">> => <<"subject">>, <<"value">> => Subject2}],
  453:     ?assertMatch(#{<<"name">> := Name2, <<"subject">> := Subject2, <<"options">> := Opts3}, get_ok_value(?CHANGE_CONFIG_PATH, Res)).
  454: 
  455: user_change_room_config_errors(Config) ->
  456:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  457:                                     fun user_change_room_config_errors_story/3).
  458: 
  459: user_change_room_config_errors_story(Config, Alice, Bob) ->
  460:     MUCServer = ?config(muc_light_host, Config),
  461:     AliceBin = escalus_client:short_jid(Alice),
  462:     BobBin = escalus_client:short_jid(Bob),
  463:     RoomName = <<"first room">>,
  464:     {ok, #{jid := #jid{luser = RoomID} = RoomJID}} =
  465:         create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
  466:     % Try to change the config with a non-existent domain
  467:     Res = user_change_room_configuration(
  468:             Alice, make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), RoomName, <<"subject2">>, Config),
  469:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res), <<"not found">>)),
  470:     % Try to change the config of the non-existent room
  471:     Res2 = user_change_room_configuration(
  472:              Alice, make_bare_jid(?UNKNOWN, MUCServer), RoomName, <<"subject2">>, Config),
  473:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"not found">>)),
  474:     % Try to change the config by the user that does not occupy this room
  475:     Res3 = user_change_room_configuration(
  476:              Bob, jid:to_binary(RoomJID), RoomName, <<"subject2">>, Config),
  477:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res3), <<"not occupy this room">>)),
  478:     % Try to change a config by the user without permission
  479:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
  480:     Res4 = user_change_room_configuration(
  481:              Bob, jid:to_binary(RoomJID), RoomName, <<"subject2">>, Config),
  482:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res4),
  483:                                           <<"does not have permission to change">>)).
  484: 
  485: user_invite_user(Config) ->
  486:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}], fun user_invite_user_story/3).
  487: 
  488: user_invite_user_story(Config, Alice, Bob) ->
  489:     MUCServer = ?config(muc_light_host, Config),
  490:     AliceBin = escalus_client:short_jid(Alice),
  491:     BobBin = escalus_client:short_jid(Bob),
  492:     Domain = escalus_client:server(Alice),
  493:     Name = <<"first room">>,
  494:     {ok, #{jid := RoomJID}} = create_room(MUCServer, Name, <<"subject2">>, AliceBin),
  495:     % Room owner can invite a user
  496:     Res = user_invite_user(Alice, jid:to_binary(RoomJID), BobBin, Config),
  497:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?INVITE_USER_PATH, Res),
  498:                                           <<"successfully">>)),
  499:     escalus:wait_for_stanza(Bob),
  500:     BobName = escalus_utils:jid_to_lower(escalus_client:username(Bob)),
  501:     AliceName = escalus_utils:jid_to_lower(escalus_client:username(Alice)),
  502:     ExpectedAff = lists:sort([{{AliceName, Domain}, owner},
  503:                               {{BobName, Domain}, member}]),
  504:     ?assertMatch(ExpectedAff, lists:sort(get_room_aff(RoomJID))).
  505: 
  506: user_invite_user_errors(Config) ->
  507:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  508:                                     fun user_invite_user_errors_story/3).
  509: 
  510: user_invite_user_errors_story(Config, Alice, Bob) ->
  511:     MUCServer = ?config(muc_light_host, Config),
  512:     AliceBin = escalus_client:short_jid(Alice),
  513:     BobBin = escalus_client:short_jid(Bob),
  514:     {ok, #{jid := #jid{luser = RoomID} = RoomJID}} =
  515:         create_room(MUCServer, <<"first room">>, <<"subject">>, AliceBin),
  516:     % Try to invite a user to not existing room
  517:     Res = user_invite_user(Alice, make_bare_jid(?UNKNOWN, MUCServer), BobBin, Config),
  518:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res), <<"not found">>)),
  519:     % User without rooms tries to invite a user
  520:     Res2 = user_invite_user(Bob, jid:to_binary(RoomJID), AliceBin, Config),
  521:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"does not occupy this room">>)),
  522:     % Try with a non-existent domain
  523:     Res3 = user_invite_user(Alice, make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), BobBin, Config),
  524:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res3), <<"not found">>)).
  525: 
  526: user_delete_room(Config) ->
  527:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}], fun user_delete_room_story/3).
  528: 
  529: user_delete_room_story(Config, Alice, Bob) ->
  530:     MUCServer = ?config(muc_light_host, Config),
  531:     AliceBin = escalus_client:short_jid(Alice),
  532:     BobBin = escalus_client:short_jid(Bob),
  533:     Name = <<"first room">>,
  534:     {ok, #{jid := #jid{luser = RoomID} = RoomJID} = RoomInfo} =
  535:         create_room(MUCServer, Name, <<"subject">>, AliceBin),
  536:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
  537:     % Member cannot delete room
  538:     Res = user_delete_room(Bob, jid:to_binary(RoomJID), Config),
  539:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res),
  540:                                           <<"cannot delete this room">>)),
  541:     % Owner can delete own room
  542:     Res2 = user_delete_room(Alice, jid:to_binary(RoomJID), Config),
  543:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?DELETE_ROOM_PATH, Res2),
  544:                                           <<"successfully">>)),
  545:     ?assertEqual({error, not_exists}, get_room_info(RoomJID), RoomInfo),
  546:     % Try with a non-existent domain
  547:     Res3 = user_delete_room(Alice, make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), Config),
  548:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res3), <<"not found">>)),
  549:     % Try with a non-existent room
  550:     Res4 = user_delete_room(Alice, make_bare_jid(?UNKNOWN, MUCServer), Config),
  551:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res4), <<"not found">>)).
  552: 
  553: user_kick_user(Config) ->
  554:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}], fun user_kick_user_story/3).
  555: 
  556: user_kick_user_story(Config, Alice, Bob) ->
  557:     MUCServer = ?config(muc_light_host, Config),
  558:     AliceBin = escalus_client:short_jid(Alice),
  559:     BobBin = escalus_client:short_jid(Bob),
  560:     RoomName = <<"first room">>,
  561:     {ok, #{jid := RoomJID}} = create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
  562:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
  563:     % Member kicks himself from a room
  564:     ?assertEqual(2, length(get_room_aff(RoomJID))),
  565:     Res = user_kick_user(Bob, jid:to_binary(RoomJID), null, Config),
  566:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?KICK_USER_PATH, Res),
  567:                                           <<"successfully">>)),
  568:     ?assertEqual(1, length(get_room_aff(RoomJID))),
  569:     % Member cannot kick the room owner.
  570:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
  571:     Res2 = user_kick_user(Bob, jid:to_binary(RoomJID), AliceBin, Config),
  572:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"does not have permission">>)),
  573:     ?assertEqual(2, length(get_room_aff(RoomJID))),
  574:     % Owner kicks the member from a room
  575:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
  576:     Res3 = user_kick_user(Alice, jid:to_binary(RoomJID), BobBin, Config),
  577:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?KICK_USER_PATH, Res3), <<"successfully">>)),
  578:     ?assertEqual(1, length(get_room_aff(RoomJID))).
  579: 
  580: user_send_message_to_room(Config) ->
  581:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  582:                                     fun user_send_message_to_room_story/3).
  583: 
  584: user_send_message_to_room_story(Config, Alice, Bob) ->
  585:     MUCServer = ?config(muc_light_host, Config),
  586:     AliceBin = escalus_client:short_jid(Alice),
  587:     BobBin = escalus_client:short_jid(Bob),
  588:     RoomName = <<"first room">>,
  589:     MsgBody = <<"Hello there!">>,
  590:     {ok, #{jid := RoomJID}} = create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
  591:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
  592:     Res = user_send_message_to_room(Alice, jid:to_binary(RoomJID), MsgBody, Config),
  593:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?SEND_MESSAGE_PATH, Res), <<"successfully">>)),
  594:     [_, Msg] = escalus:wait_for_stanzas(Bob, 2),
  595:     escalus:assert(is_message, Msg).
  596: 
  597: user_send_message_to_room_errors(Config) ->
  598:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  599:                                     fun user_send_message_to_room_errors_story/3).
  600: 
  601: user_send_message_to_room_errors_story(Config, Alice, Bob) ->
  602:     MUCServer = ?config(muc_light_host, Config),
  603:     AliceBin = escalus_client:short_jid(Alice),
  604:     BobBin = escalus_client:short_jid(Bob),
  605:     MsgBody = <<"Hello there!">>,
  606:     {ok, #{jid := #jid{luser = ARoomID} = ARoomJID}} =
  607:         create_room(MUCServer, <<"alice room">>, <<"subject">>, AliceBin),
  608:     % Try with a non-existent domain
  609:     Res = user_send_message_to_room(
  610:             Alice, make_bare_jid(ARoomID, ?UNKNOWN_DOMAIN), MsgBody, Config),
  611:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res), <<"not found">>)),
  612:     % Try with a user without rooms
  613:     Res2 = user_send_message_to_room(Bob, jid:to_binary(ARoomJID), MsgBody, Config),
  614:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"not occupy this room">>)),
  615:     % Try with a room not occupied by this user
  616:     {ok, #{jid := _RoomJID2}} = create_room(MUCServer, <<"bob room">>, <<"subject">>, BobBin),
  617:     Res3 = user_send_message_to_room(Bob, jid:to_binary(ARoomJID), MsgBody, Config),
  618:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res3), <<"not occupy this room">>)).
  619: 
  620: user_get_room_messages(Config) ->
  621:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}], fun user_get_room_messages_story/3).
  622: 
  623: user_get_room_messages_story(Config, Alice, Bob) ->
  624:     MUCServer = ?config(muc_light_host, Config),
  625:     AliceBin = escalus_client:short_jid(Alice),
  626:     {ok, #{jid := #jid{luser = RoomID} = RoomJID}} =
  627:         create_room(MUCServer, <<"first room">>, <<"subject">>, AliceBin),
  628:     Message = <<"Hello friends">>,
  629:     send_message_to_room(RoomJID, jid:from_binary(AliceBin), Message),
  630:     mam_helper:wait_for_room_archive_size(MUCServer, RoomID, 1),
  631:     % Get messages so far
  632:     Limit = 40,
  633:     Res = user_get_room_messages(Alice, jid:to_binary(RoomJID), Limit, null, Config),
  634:     #{<<"stanzas">> :=[#{<<"stanza">> := StanzaXML}], <<"limit">> := Limit} =
  635:         get_ok_value(?GET_MESSAGES_PATH, Res),
  636:     ?assertMatch({ok, #xmlel{name = <<"message">>}}, exml:parse(StanzaXML)),
  637:     % Get messages before the given date and time
  638:     Before = <<"2022-02-17T04:54:13+00:00">>,
  639:     Res2 = user_get_room_messages(Alice, jid:to_binary(RoomJID), null, Before, Config),
  640:     ?assertMatch(#{<<"stanzas">> := [], <<"limit">> := 50}, get_ok_value(?GET_MESSAGES_PATH, Res2)),
  641:     % Try to pass too big page size value
  642:     Res3 = user_get_room_messages(Alice, jid:to_binary(RoomJID), 51, Before, Config),
  643:     ?assertMatch(#{<<"limit">> := 50}, get_ok_value(?GET_MESSAGES_PATH, Res3)),
  644:     % Try with a non-existent domain
  645:     Res4 = user_get_room_messages(
  646:              Alice, make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), Limit, null, Config),
  647:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res4), <<"server not found">>)),
  648:     % Try with a user that is not a room member
  649:     Res5 = user_get_room_messages(Bob, jid:to_binary(RoomJID), Limit, null, Config),
  650:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res5), <<"not occupy this room">>)).
  651: 
  652: user_shouldnt_store_messages_in_muc(Config) ->
  653:     muc_helper:story_with_room(Config, [], [{alice, 1}],
  654:                                fun user_shouldnt_store_messages_in_muc_story/2).
  655: 
  656: user_shouldnt_store_messages_in_muc_story(Config, Alice) ->
  657:     %% Enter a MUC room
  658:     MUCRoomJID = jid:from_binary(?config(room_jid, Config)),
  659:     enter_muc_room(MUCRoomJID, Alice, <<"Ali">>),
  660:     escalus:wait_for_stanza(Alice),
  661:     %% Send a message
  662:     Message = <<"Hello friends">>,
  663:     send_message_to_muc_room(Alice, MUCRoomJID, Message, null, Config),
  664:     escalus:wait_for_stanza(Alice),
  665:     %% Try to get a MUC message
  666:     Limit = 1,
  667:     Res3 = user_get_muc_room_messages(Alice, jid:to_binary(MUCRoomJID), Limit, null, Config),
  668:     #{<<"stanzas">> := [], <<"limit">> := Limit} = get_ok_value([data, muc, getRoomMessages], Res3).
  669: 
  670: user_list_rooms(Config) ->
  671:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun user_list_rooms_story/2).
  672: 
  673: user_list_rooms_story(Config, Alice) ->
  674:     MUCServer = ?config(muc_light_host, Config),
  675:     AliceBin = escalus_client:short_jid(Alice),
  676:     {ok, #{jid := RoomJID}} = create_room(MUCServer, <<"room a">>, <<"subject">>, AliceBin),
  677:     {ok, #{jid := RoomJID2}} = create_room(MUCServer, <<"room b">>, <<"subject">>, AliceBin),
  678:     Res = user_list_rooms(Alice, Config),
  679:     ?assertEqual(lists:sort([jid:to_binary(RoomJID), jid:to_binary(RoomJID2)]),
  680:                  lists:sort(get_ok_value(?USER_LIST_ROOMS_PATH, Res))).
  681: 
  682: user_list_room_users(Config) ->
  683:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}], fun user_list_room_users_story/3).
  684: 
  685: user_list_room_users_story(Config, Alice, Bob) ->
  686:     MUCServer = ?config(muc_light_host, Config),
  687:     AliceBin = escalus_client:short_jid(Alice),
  688:     BobBin = escalus_client:short_jid(Bob),
  689:     AliceLower = escalus_utils:jid_to_lower(AliceBin),
  690:     {ok, #{jid := RoomJID}} = create_room(MUCServer, <<"room a">>, <<"subject">>, AliceBin),
  691:     % Owner can list room users
  692:     Res = user_list_room_users(Alice, jid:to_binary(RoomJID), Config),
  693:     ?assertEqual([#{<<"jid">> => AliceLower, <<"affiliation">> => <<"OWNER">>}],
  694:                  get_ok_value(?LIST_ROOM_USERS_PATH, Res)),
  695:     % Try with a non-existent domain
  696:     Res2 = user_list_room_users(Alice, make_bare_jid(RoomJID#jid.luser, ?UNKNOWN_DOMAIN), Config),
  697:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"not found">>)),
  698:     % Try with a non-existent room
  699:     Res3 = user_list_room_users(Alice, make_bare_jid(?UNKNOWN, MUCServer), Config),
  700:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res3), <<"not found">>)),
  701:     % User that is not a member cannot get aff
  702:     Res4 = user_list_room_users(Bob, jid:to_binary(RoomJID), Config),
  703:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res4), <<"not occupy this room">>)),
  704:     % Member can get aff
  705:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
  706:     escalus:wait_for_stanza(Bob),
  707:     Res5 = user_list_room_users(Bob, jid:to_binary(RoomJID), Config),
  708:     ?assertMatch([_, _], get_ok_value(?LIST_ROOM_USERS_PATH, Res5)).
  709: 
  710: user_get_room_config(Config) ->
  711:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}], fun user_get_room_config_story/3).
  712: 
  713: user_get_room_config_story(Config, Alice, Bob) ->
  714:     MUCServer = ?config(muc_light_host, Config),
  715:     AliceBin = escalus_client:short_jid(Alice),
  716:     BobBin = escalus_client:short_jid(Bob),
  717:     AliceLower = escalus_utils:jid_to_lower(AliceBin),
  718:     BobLower = escalus_utils:jid_to_lower(BobBin),
  719:     RoomName = <<"first room">>,
  720:     RoomSubject = <<"Room about nothing">>,
  721:     {ok, #{jid := #jid{luser = RoomID} = RoomJID}} =
  722:         create_room(MUCServer, RoomName, RoomSubject, AliceBin),
  723:     RoomJIDBin = jid:to_binary(RoomJID),
  724:     Res = user_get_room_config(Alice, jid:to_binary(RoomJID), Config),
  725:     % Owner can get a config
  726:     ?assertEqual(#{<<"jid">> => RoomJIDBin, <<"subject">> => RoomSubject, <<"name">> => RoomName,
  727:                     <<"options">> => [#{<<"key">> => <<"background">>, <<"value">> => <<>>},
  728:                                       #{<<"key">> => <<"music">>, <<"value">> => <<>>},
  729:                                       #{<<"key">> => <<"roomname">>, <<"value">> => RoomName},
  730:                                       #{<<"key">> => <<"subject">>, <<"value">> => RoomSubject}],
  731:                     <<"participants">> => [#{<<"jid">> => AliceLower,
  732:                                              <<"affiliation">> => <<"OWNER">>}]},
  733:                  get_ok_value(?GET_ROOM_CONFIG_PATH, Res)),
  734:     % Try with a non-existent domain
  735:     Res2 = user_get_room_config(Alice, make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), Config),
  736:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"not found">>)),
  737:     % Try with a non-existent room
  738:     Res3 = user_get_room_config(Alice, make_bare_jid(?UNKNOWN, MUCServer), Config),
  739:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res3), <<"not found">>)),
  740:     % User that is not a member cannot get a room config
  741:     Res4 = user_get_room_config(Bob, jid:to_binary(RoomJID), Config),
  742:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res4), <<"not occupy this room">>)),
  743:     % Member can get a config
  744:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
  745:     Res5 = user_get_room_config(Bob, jid:to_binary(RoomJID), Config),
  746:     ?assertEqual(#{<<"jid">> => RoomJIDBin, <<"subject">> => RoomSubject, <<"name">> => RoomName,
  747:                     <<"options">> => [#{<<"key">> => <<"background">>, <<"value">> => <<>>},
  748:                                       #{<<"key">> => <<"music">>, <<"value">> => <<>>},
  749:                                       #{<<"key">> => <<"roomname">>, <<"value">> => RoomName},
  750:                                       #{<<"key">> => <<"subject">>, <<"value">> => RoomSubject}],
  751:                     <<"participants">> => [#{<<"jid">> => AliceLower,
  752:                                              <<"affiliation">> => <<"OWNER">>},
  753:                                            #{<<"jid">> => BobLower,
  754:                                              <<"affiliation">> => <<"MEMBER">>}]},
  755:                  get_ok_value(?GET_ROOM_CONFIG_PATH, Res5)).
  756: 
  757: user_blocking_list(Config) ->
  758:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}], fun user_blocking_list_story/3).
  759: 
  760: user_blocking_list_story(Config, Alice, Bob) ->
  761:     BobBin = escalus_client:full_jid(Bob),
  762:     BobShortBin = escalus_utils:jid_to_lower(escalus_client:short_jid(Bob)),
  763:     {ok, #{jid := RoomJID}} = create_room(?config(muc_light_host, Config),
  764:                                           <<"room">>, <<"subject">>, BobBin),
  765:     RoomBin = jid:to_binary(RoomJID),
  766:     Res = user_get_blocking(Alice, Config),
  767:     ?assertMatch([], get_ok_value(?GET_BLOCKING_LIST_PATH, Res)),
  768:     Res2 = user_set_blocking(Alice, [{<<"USER">>, <<"DENY">>, BobBin}], Config),
  769:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?SET_BLOCKING_LIST_PATH, Res2),
  770:                                           <<"successfully">>)),
  771:     Res3 = user_get_blocking(Alice, Config),
  772:     ?assertEqual([#{<<"entityType">> => <<"USER">>,
  773:                     <<"action">> => <<"DENY">>,
  774:                     <<"entity">> => BobShortBin}],
  775:                  get_ok_value(?GET_BLOCKING_LIST_PATH, Res3)),
  776:     Res4 = user_set_blocking(Alice, [{<<"USER">>, <<"ALLOW">>, BobBin},
  777:                                      {<<"ROOM">>, <<"DENY">>, jid:to_binary(RoomJID)}], Config),
  778:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?SET_BLOCKING_LIST_PATH, Res4),
  779:                                           <<"successfully">>)),
  780:     Res5 = user_get_blocking(Alice, Config),
  781:     ?assertEqual([#{<<"entityType">> => <<"ROOM">>,
  782:                     <<"action">> => <<"DENY">>,
  783:                     <<"entity">> => RoomBin}],
  784:                  get_ok_value(?GET_BLOCKING_LIST_PATH, Res5)).
  785: 
  786: %% Domain admin test cases
  787: 
  788: domain_admin_create_room_no_permission(Config) ->
  789:     escalus:fresh_story_with_config(Config, [{alice, 1}, {alice_bis, 1}],
  790:                                     fun domain_admin_create_room_no_permission_story/3).
  791: 
  792: domain_admin_create_room_no_permission_story(Config, Alice, AliceBis) ->
  793:     AliceBin = escalus_client:short_jid(Alice),
  794:     AliceBisBin = escalus_client:short_jid(AliceBis),
  795:     InvalidUser = make_bare_jid(?UNKNOWN, ?UNKNOWN_DOMAIN),
  796:     MucServer = ?config(muc_light_host, Config),
  797:     ExternalMucServer = ?config(secondary_muc_light_host, Config),
  798:     Name = <<"first room">>,
  799:     Subject = <<"testing">>,
  800:     % Try with a non-existent domain
  801:     Res = create_room(MucServer, Name, InvalidUser, Subject, null, Config),
  802:     get_unauthorized(Res),
  803:     % Try with an external domain
  804:     Res2 = create_room(MucServer, Name, AliceBisBin, Subject, null, Config),
  805:     get_unauthorized(Res2),
  806:     % Try to create a room at an external domain
  807:     Res3 = create_room(ExternalMucServer, Name, AliceBin, Subject, null, Config),
  808:     get_unauthorized(Res3).
  809: 
  810: domain_admin_create_identified_room_no_permission(Config) ->
  811:     escalus:fresh_story_with_config(Config, [{alice_bis, 1}],
  812:                                     fun domain_admin_create_identified_room_no_permission_story/2).
  813: 
  814: domain_admin_create_identified_room_no_permission_story(Config, AliceBis) ->
  815:     AliceBisBin = escalus_client:short_jid(AliceBis),
  816:     InvalidUser = make_bare_jid(?UNKNOWN, ?UNKNOWN_DOMAIN),
  817:     MucServer = ?config(muc_light_host, Config),
  818:     Name = <<"first room">>,
  819:     Subject = <<"testing">>,
  820:     SchemaEndpoint = atom_to_binary(?config(schema_endpoint, Config)),
  821:     Protocol = atom_to_binary(?config(protocol, Config)),
  822:     Id = <<"my_room_", SchemaEndpoint/binary, "_", Protocol/binary>>,
  823:     % Try with a non-existent domain
  824:     Res = create_room(MucServer, Name, InvalidUser, Subject, Id, Config),
  825:     get_unauthorized(Res),
  826:     % Try with an external domain
  827:     Res2 = create_room(MucServer, Name, AliceBisBin, Subject, Id, Config),
  828:     get_unauthorized(Res2).
  829: 
  830: domain_admin_change_room_config_no_permission(Config) ->
  831:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  832:                                     fun domain_admin_change_room_config_no_permission_story/3).
  833: 
  834: domain_admin_change_room_config_no_permission_story(Config, Alice, Bob) ->
  835:     AliceBin = escalus_client:short_jid(Alice),
  836:     BobBin = escalus_client:short_jid(Bob),
  837:     MUCServer = ?config(secondary_muc_light_host, Config),
  838:     RoomName = <<"first room">>,
  839:     {ok, #{jid := #jid{luser = RoomID} = RoomJID}} =
  840:         create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
  841:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
  842:     RoomJIDBin = jid:to_binary(RoomJID),
  843:     Res = change_room_configuration(RoomJIDBin, AliceBin, RoomName, <<"subject">>, Config),
  844:     get_unauthorized(Res),
  845:     % Try to change the config with an external domain
  846:     Res2 = change_room_configuration(
  847:             make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), AliceBin, RoomName, <<"subject2">>, Config),
  848:     get_unauthorized(Res2).
  849: 
  850: domain_admin_invite_user_no_permission(Config) ->
  851:     escalus:fresh_story_with_config(Config, [{alice_bis, 1}, {bob, 1}],
  852:                                     fun domain_admin_invite_user_no_permission_story/3).
  853: 
  854: domain_admin_invite_user_no_permission_story(Config, AliceBis, Bob) ->
  855:     AliceBisBin = escalus_client:short_jid(AliceBis),
  856:     BobBin = escalus_client:short_jid(Bob),
  857:     MUCServer = ?config(muc_light_host, Config),
  858:     Name = <<"first room">>,
  859:     {ok, #{jid := RoomJID}} = create_room(MUCServer, Name, <<"subject2">>, AliceBisBin),
  860:     Res = invite_user(jid:to_binary(RoomJID), AliceBisBin, BobBin, Config),
  861:     get_unauthorized(Res).
  862: 
  863: domain_admin_delete_room_no_permission(Config) ->
  864:     escalus:fresh_story_with_config(Config, [{alice, 1}],
  865:                                     fun domain_admin_delete_room_no_permission_story/2).
  866: 
  867: domain_admin_delete_room_no_permission_story(Config, Alice) ->
  868:     AliceBin = escalus_client:short_jid(Alice),
  869:     RoomName = <<"first room">>,
  870:     MUCServer = ?config(secondary_muc_light_host, Config),
  871:     {ok, #{jid := #jid{luser = RoomID} = RoomJID}} =
  872:         create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
  873:     RoomJIDBin = jid:to_binary(RoomJID),
  874:     Res = delete_room(RoomJIDBin, Config),
  875:     get_unauthorized(Res),
  876:     % Try with a non-existent domain
  877:     Res2 = delete_room(make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), Config),
  878:     get_unauthorized(Res2).
  879: 
  880: domain_admin_kick_user_no_permission(Config) ->
  881:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  882:                                     fun domain_admin_kick_user_no_permission_story/3).
  883: 
  884: domain_admin_kick_user_no_permission_story(Config, Alice, Bob) ->
  885:     AliceBin = escalus_client:short_jid(Alice),
  886:     BobBin = escalus_client:short_jid(Bob),
  887:     RoomName = <<"first room">>,
  888:     MUCServer = ?config(secondary_muc_light_host, Config),
  889:     {ok, #{jid := #jid{luser = RoomID} = RoomJID}} =
  890:         create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
  891:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
  892:     RoomJIDBin = jid:to_binary(RoomJID),
  893:     ?assertEqual(2, length(get_room_aff(RoomJID))),
  894:     Res = kick_user(RoomJIDBin, BobBin, Config),
  895:     get_unauthorized(Res),
  896:     % Try with a non-existent domain
  897:     Res2 = kick_user(make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), BobBin, Config),
  898:     get_unauthorized(Res2).
  899: 
  900: domain_admin_send_message_to_room_no_permission(Config) ->
  901:     escalus:fresh_story_with_config(Config, [{alice_bis, 1}, {bob, 1}],
  902:                                     fun domain_admin_send_message_to_room_no_permission_story/3).
  903: 
  904: domain_admin_send_message_to_room_no_permission_story(Config, AliceBis, Bob) ->
  905:     AliceBisBin = escalus_client:short_jid(AliceBis),
  906:     InvalidUser = make_bare_jid(?UNKNOWN, ?UNKNOWN_DOMAIN),
  907:     BobBin = escalus_client:short_jid(Bob),
  908:     MUCServer = ?config(muc_light_host, Config),
  909:     RoomName = <<"first room">>,
  910:     MsgBody = <<"Hello there!">>,
  911:     {ok, #{jid := RoomJID}} = create_room(MUCServer, RoomName, <<"subject">>, AliceBisBin),
  912:     {ok, _} = invite_user(RoomJID, AliceBisBin, BobBin),
  913:     % Try with a non-existent domain
  914:     Res = send_message_to_room(jid:to_binary(RoomJID), InvalidUser, MsgBody, Config),
  915:     get_unauthorized(Res),
  916:     % Try with an external domain room
  917:     Res2 = send_message_to_room(jid:to_binary(RoomJID), AliceBisBin, MsgBody, Config),
  918:     get_unauthorized(Res2).
  919: 
  920: domain_admin_get_room_messages_no_permission(Config) ->
  921:     escalus:fresh_story_with_config(Config, [{alice, 1}],
  922:                                     fun domain_admin_get_room_messages_no_permission_story/2).
  923: 
  924: domain_admin_get_room_messages_no_permission_story(Config, Alice) ->
  925:     AliceBin = escalus_client:short_jid(Alice),
  926:     MUCServer = ?config(secondary_muc_light_host, Config),
  927:     RoomName = <<"first room">>,
  928:     Limit = 40,
  929:     {ok, #{jid := #jid{luser = RoomID} = RoomJID}} =
  930:         create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
  931:     RoomJIDBin = jid:to_binary(RoomJID),
  932:     Res = get_room_messages(RoomJIDBin, Limit, null, Config),
  933:     get_unauthorized(Res),
  934:     % Try with a non-existent domain
  935:     Res2 = get_room_messages(make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), Limit, null, Config),
  936:     get_unauthorized(Res2).
  937: 
  938: domain_admin_list_user_rooms_no_permission(Config) ->
  939:     escalus:fresh_story_with_config(Config, [{alice_bis, 1}],
  940:                                     fun domain_admin_list_user_rooms_no_permission_story/2).
  941: 
  942: domain_admin_list_user_rooms_no_permission_story(Config, AliceBis) ->
  943:     AliceBisBin = escalus_client:short_jid(AliceBis),
  944:     InvalidUser = make_bare_jid(?UNKNOWN, ?UNKNOWN_DOMAIN),
  945:     % Try with a non-existent domain
  946:     Res = list_user_rooms(InvalidUser, Config),
  947:     get_unauthorized(Res),
  948:     % Try with an external domain
  949:     Res2 = list_user_rooms(AliceBisBin, Config),
  950:     get_unauthorized(Res2).
  951: 
  952: domain_admin_list_room_users_no_permission(Config) ->
  953:     escalus:fresh_story_with_config(Config, [{alice, 1}],
  954:                                     fun domain_admin_list_room_users_story_no_permission/2).
  955: 
  956: domain_admin_list_room_users_story_no_permission(Config, Alice) ->
  957:     AliceBin = escalus_client:short_jid(Alice),
  958:     MUCServer = ?config(secondary_muc_light_host, Config),
  959:     RoomName = <<"first room">>,
  960:     {ok, #{jid := #jid{luser = RoomID} = RoomJID}} =
  961:         create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
  962:     RoomJIDBin = jid:to_binary(RoomJID),
  963:     Res = list_room_users(RoomJIDBin, Config),
  964:     get_unauthorized(Res),
  965:     % Try with an external domain
  966:     Res2 = list_room_users(make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), Config),
  967:     get_unauthorized(Res2).
  968: 
  969: domain_admin_get_room_config_no_permission(Config) ->
  970:     escalus:fresh_story_with_config(Config, [{alice, 1}],
  971:                                     fun domain_admin_get_room_config_no_permission_story/2).
  972: 
  973: domain_admin_get_room_config_no_permission_story(Config, Alice) ->
  974:     AliceBin = escalus_client:short_jid(Alice),
  975:     MUCServer = ?config(secondary_muc_light_host, Config),
  976:     RoomName = <<"first room">>,
  977:     {ok, #{jid := #jid{luser = RoomID} = RoomJID}} =
  978:         create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
  979:     RoomJIDBin = jid:to_binary(RoomJID),
  980:     Res = get_room_config(RoomJIDBin, Config),
  981:     get_unauthorized(Res),
  982:     % Try with a non-existent domain
  983:     Res2 = get_room_config(make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), Config),
  984:     get_unauthorized(Res2).
  985: 
  986: domain_admin_blocking_list_no_permission(Config) ->
  987:     escalus:fresh_story_with_config(Config, [{alice_bis, 1}],
  988:                                     fun domain_admin_blocking_list_no_permission_story/2).
  989: 
  990: domain_admin_blocking_list_no_permission_story(Config, AliceBis) ->
  991:     AliceBisBin = escalus_client:full_jid(AliceBis),
  992:     InvalidUser = make_bare_jid(?UNKNOWN, ?UNKNOWN_DOMAIN),
  993:     % Try with a non-existent user
  994:     Res = get_user_blocking(InvalidUser, Config),
  995:     get_unauthorized(Res),
  996:     Res2 = set_blocking(InvalidUser, [], Config),
  997:     get_unauthorized(Res2),
  998:     % Try with an external domain user
  999:     Res3 = get_user_blocking(AliceBisBin, Config),
 1000:     get_unauthorized(Res3),
 1001:     Res4 = set_blocking(AliceBisBin, [], Config),
 1002:     get_unauthorized(Res4).
 1003: 
 1004: %% Admin test cases
 1005: 
 1006: admin_blocking_list(Config) ->
 1007:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}], fun admin_blocking_list_story/3).
 1008: 
 1009: admin_blocking_list_story(Config, Alice, Bob) ->
 1010:     AliceBin = escalus_client:full_jid(Alice),
 1011:     BobBin = escalus_client:full_jid(Bob),
 1012:     BobShortBin = escalus_utils:jid_to_lower(escalus_client:short_jid(Bob)),
 1013:     Res = get_user_blocking(AliceBin, Config),
 1014:     ?assertMatch([], get_ok_value(?GET_BLOCKING_LIST_PATH, Res)),
 1015:     Res2 = set_blocking(AliceBin, [{<<"USER">>, <<"DENY">>, BobBin}], Config),
 1016:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?SET_BLOCKING_LIST_PATH, Res2),
 1017:                                           <<"successfully">>)),
 1018:     Res3 = get_user_blocking(AliceBin, Config),
 1019:     ?assertEqual([#{<<"entityType">> => <<"USER">>,
 1020:                     <<"action">> => <<"DENY">>,
 1021:                     <<"entity">> => BobShortBin}],
 1022:                  get_ok_value(?GET_BLOCKING_LIST_PATH, Res3)),
 1023:     Res4 = set_blocking(AliceBin, [{<<"USER">>, <<"ALLOW">>, BobBin}], Config),
 1024:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?SET_BLOCKING_LIST_PATH, Res4),
 1025:                                           <<"successfully">>)),
 1026:     Res5 = get_user_blocking(AliceBin, Config),
 1027:     ?assertMatch([], get_ok_value(?GET_BLOCKING_LIST_PATH, Res5)).
 1028: 
 1029: admin_blocking_list_null(Config) ->
 1030:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
 1031:                                     fun admin_blocking_list_null_story/3).
 1032: 
 1033: admin_blocking_list_null_story(Config, Alice, Bob) ->
 1034:     AliceBin = escalus_client:full_jid(Alice),
 1035:     BobBin = escalus_client:full_jid(Bob),
 1036:     BobShortBin = escalus_utils:jid_to_lower(escalus_client:short_jid(Bob)),
 1037:     Res = get_user_blocking(AliceBin, Config),
 1038:     ?assertMatch([], get_ok_value(?GET_BLOCKING_LIST_PATH, Res)),
 1039:     Res2 = set_blocking(AliceBin, [{<<"USER">>, null, BobBin}], Config),
 1040:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?SET_BLOCKING_LIST_PATH, Res2),
 1041:                                             <<"successfully">>)),
 1042:     Res3 = get_user_blocking(AliceBin, Config),
 1043:     ?assertEqual([#{<<"entityType">> => <<"USER">>,
 1044:                     <<"action">> => <<"DENY">>,
 1045:                     <<"entity">> => BobShortBin}],
 1046:                     get_ok_value(?GET_BLOCKING_LIST_PATH, Res3)),
 1047:     Res4 = set_blocking(AliceBin, [{<<"USER">>, <<"ALLOW">>, BobBin}], Config),
 1048:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?SET_BLOCKING_LIST_PATH, Res4),
 1049:                                             <<"successfully">>)),
 1050:     Res5 = get_user_blocking(AliceBin, Config),
 1051:     ?assertMatch([], get_ok_value(?GET_BLOCKING_LIST_PATH, Res5)).
 1052: 
 1053: admin_blocking_list_errors(Config) ->
 1054:     InvalidUser = make_bare_jid(?UNKNOWN, ?UNKNOWN_DOMAIN),
 1055:     Res = get_user_blocking(InvalidUser, Config),
 1056:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res), <<"domain does not exist">>)),
 1057:     Res2 = set_blocking(InvalidUser, [], Config),
 1058:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"domain does not exist">>)),
 1059:     BadUser = make_bare_jid(<<"baduser">>, domain_helper:domain()),
 1060:     Res3 = get_user_blocking(BadUser, Config),
 1061:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res3), <<"user does not exist">>)),
 1062:     Res4 = set_blocking(BadUser, [], Config),
 1063:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res4), <<"user does not exist">>)).
 1064: 
 1065: admin_create_room(Config) ->
 1066:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun admin_create_room_story/2).
 1067: 
 1068: admin_create_room_story(Config, Alice) ->
 1069:     AliceBin = escalus_client:short_jid(Alice),
 1070:     AliceBinLower = escalus_utils:jid_to_lower(AliceBin),
 1071:     MucServer = ?config(muc_light_host, Config),
 1072:     Name = <<"first room">>,
 1073:     Subject = <<"testing">>,
 1074:     Res = create_room(MucServer, Name, AliceBin, Subject, null, Config),
 1075:     #{<<"jid">> := JID, <<"name">> := Name, <<"subject">> := Subject,
 1076:       <<"participants">> := Participants} = get_ok_value(?CREATE_ROOM_PATH, Res),
 1077:     ?assertMatch(#jid{lserver = MucServer}, jid:from_binary(JID)),
 1078:     ?assertEqual([#{<<"jid">> => AliceBinLower, <<"affiliation">> => <<"OWNER">>}], Participants),
 1079:     % Try with a non-existent user
 1080:     BadUser = make_bare_jid(<<"baduser">>, domain_helper:domain()),
 1081:     Res1 = create_room(?config(muc_light_host, Config), null, BadUser, null, null, Config),
 1082:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res1), <<"user does not exist">>)).
 1083: 
 1084: admin_create_room_non_existent_domain(Config) ->
 1085:     Config1 = escalus_fresh:create_users(Config, [{alice, 1}]),
 1086:     AliceBin = escalus_users:get_jid(Config1, alice),
 1087:     MucServer = ?config(muc_light_host, Config),
 1088:     Res1 = create_room(?UNKNOWN_DOMAIN, null, AliceBin, null, null, Config1),
 1089:     ?assertMatch({_, _}, binary:match(get_err_msg(Res1), <<"MUC Light server not found">>)),
 1090:     BadUser = make_bare_jid(<<"baduser">>, ?UNKNOWN_DOMAIN),
 1091:     Res2 = create_room(MucServer, null, BadUser, null, null, Config1),
 1092:     ?assertMatch({_, _}, binary:match(get_err_msg(Res2), <<"User's domain does not exist">>)).
 1093: 
 1094: admin_create_room_with_unprepped_domain(Config) ->
 1095:     FreshConfig = escalus_fresh:create_users(Config, [{alice, 1}]),
 1096:     AliceBin = escalus_users:get_jid(FreshConfig, alice),
 1097:     MucServer = ?config(muc_light_host, Config),
 1098:     Name = <<"room with unprepped domain">>,
 1099:     Subject = <<"testing">>,
 1100:     Res = create_room(unprep(MucServer), Name, AliceBin, Subject, null, Config),
 1101:     #{<<"jid">> := JID, <<"name">> := Name, <<"subject">> := Subject} =
 1102:         get_ok_value(?CREATE_ROOM_PATH, Res),
 1103:     ?assertMatch(#jid{lserver = MucServer}, jid:from_binary_noprep(JID)).
 1104: 
 1105: admin_create_room_with_custom_fields(Config) ->
 1106:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun admin_create_room_with_custom_fields_story/2).
 1107: 
 1108: admin_create_room_with_custom_fields_story(Config, Alice) ->
 1109:     AliceBin = escalus_client:short_jid(Alice),
 1110:     AliceBinLower = escalus_utils:jid_to_lower(AliceBin),
 1111:     MucServer = ?config(muc_light_host, Config),
 1112:     Name = <<"first room">>,
 1113:     Subject = <<"testing">>,
 1114:     Options = #{<<"background">> => <<"red">>},
 1115:     Opts = [#{<<"key">> => <<"background">>, <<"value">> => <<"red">>},
 1116:             #{<<"key">> => <<"roomname">>, <<"value">> => Name},
 1117:             #{<<"key">> => <<"subject">>, <<"value">> => Subject}],
 1118:     Res = create_room_with_custom_fields(MucServer, Name, AliceBin, Subject, null, Config, Options),
 1119:     #{<<"jid">> := JID, <<"name">> := Name, <<"subject">> := Subject,
 1120:       <<"participants">> := Participants, <<"options">> := Opts} = get_ok_value(?CREATE_ROOM_PATH, Res),
 1121:     ?assertMatch(#jid{lserver = MucServer}, jid:from_binary(JID)),
 1122:     ?assertEqual([#{<<"jid">> => AliceBinLower, <<"affiliation">> => <<"OWNER">>}], Participants).
 1123: 
 1124: admin_create_identified_room(Config) ->
 1125:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun admin_create_identified_room_story/2).
 1126: 
 1127: admin_create_identified_room_story(Config, Alice) ->
 1128:     AliceBin = escalus_client:short_jid(Alice),
 1129:     MucServer = ?config(muc_light_host, Config),
 1130:     Name = <<"first room">>,
 1131:     Subject = <<"testing">>,
 1132:     SchemaEndpoint = atom_to_binary(?config(schema_endpoint, Config)),
 1133:     Protocol = atom_to_binary(?config(protocol, Config)),
 1134:     Id = <<"my_room_", SchemaEndpoint/binary, "_", Protocol/binary>>,
 1135:     Res = create_room(MucServer, Name, AliceBin, Subject, Id, Config),
 1136:     #{<<"jid">> := JID, <<"name">> := Name, <<"subject">> := Subject} =
 1137:         get_ok_value(?CREATE_ROOM_PATH, Res),
 1138:     ?assertMatch(#jid{luser = Id, lserver = MucServer}, jid:from_binary(JID)),
 1139:     % Create a room with an existing ID
 1140:     Res1 = create_room(MucServer, <<"snd room">>, AliceBin, Subject, Id, Config),
 1141:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res1), <<"already exists">>)),
 1142:     % Try with a non-existent user
 1143:     BadUser = make_bare_jid(<<"baduser">>, domain_helper:domain()),
 1144:     Res2 = create_room(?config(muc_light_host, Config), null, BadUser, null, Id, Config),
 1145:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"user does not exist">>)).
 1146: 
 1147: admin_create_identified_room_non_existent_domain(Config) ->
 1148:     Config1 = escalus_fresh:create_users(Config, [{alice, 1}]),
 1149:     AliceBin = escalus_users:get_jid(Config1, alice),
 1150:     Id = <<"bad_room">>,
 1151:     MucServer = ?config(muc_light_host, Config),
 1152:     Res1 = create_room(?UNKNOWN_DOMAIN, null, AliceBin, null, Id, Config1),
 1153:     ?assertMatch({_, _}, binary:match(get_err_msg(Res1), <<"MUC Light server not found">>)),
 1154:     BadUser = make_bare_jid(<<"baduser">>, ?UNKNOWN_DOMAIN),
 1155:     Res2 = create_room(MucServer, null, BadUser, null, Id, Config1),
 1156:     ?assertMatch({_, _}, binary:match(get_err_msg(Res2), <<"User's domain does not exist">>)).
 1157: 
 1158: admin_create_room_with_unprepped_id(Config) ->
 1159:     FreshConfig = escalus_fresh:create_users(Config, [{alice, 1}]),
 1160:     AliceBin = escalus_users:get_jid(FreshConfig, alice),
 1161:     MucServer = ?config(muc_light_host, FreshConfig),
 1162:     Name = <<"first room">>,
 1163:     Subject = <<"testing">>,
 1164:     Id = <<"room_with_unprepped_id">>,
 1165:     Res = create_room(unprep(MucServer), Name, AliceBin, Subject, unprep(Id), FreshConfig),
 1166:     #{<<"jid">> := JID, <<"name">> := Name, <<"subject">> := Subject} =
 1167:         get_ok_value(?CREATE_ROOM_PATH, Res),
 1168:     ?assertMatch(#jid{luser = Id, lserver = MucServer}, jid:from_binary_noprep(JID)).
 1169: 
 1170: admin_change_room_config(Config) ->
 1171:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun admin_change_room_config_story/2).
 1172: 
 1173: admin_change_room_config_story(Config, Alice) ->
 1174:     AliceBin = escalus_client:short_jid(Alice),
 1175:     MUCServer = ?config(muc_light_host, Config),
 1176:     Name = <<"first room">>,
 1177:     Subject = <<"testing">>,
 1178:     % Create a new room
 1179:     {ok, #{jid := RoomJID}} = create_room(MUCServer, Name, Subject, AliceBin),
 1180:     % Try to change the room configuration
 1181:     Name2 = <<"changed room">>,
 1182:     Subject2 = <<"not testing">>,
 1183:     Res = change_room_configuration(jid:to_binary(RoomJID), AliceBin, Name2, Subject2, Config),
 1184:     ?assertMatch(#{<<"name">> := Name2, <<"subject">> := Subject2},
 1185:                  get_ok_value(?CHANGE_CONFIG_PATH, Res)).
 1186: 
 1187: admin_change_room_config_with_custom_fields(Config) ->
 1188:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun admin_change_room_config_with_custom_fields_story/2).
 1189: 
 1190: admin_change_room_config_with_custom_fields_story(Config, Alice) ->
 1191:     AliceBin = escalus_client:short_jid(Alice),
 1192:     MUCServer = ?config(muc_light_host, Config),
 1193:     Name = <<"first room">>,
 1194:     Subject = <<"testing">>,
 1195:     Opts = #{<<"background">> => <<"red">>},
 1196:     % Create a new room
 1197:     Res = create_room_with_custom_fields(MUCServer, Name, AliceBin, Subject, null, Config, Opts),
 1198:     #{<<"jid">> := RoomJID} = get_ok_value(?CREATE_ROOM_PATH, Res),
 1199:     % Try to change the room configuration
 1200:     Name2 = <<"changed room">>,
 1201:     Subject2 = <<"not testing">>,
 1202:     Opts2 = #{<<"music">> => <<"sad">>},
 1203:     Res2 = change_room_configuration_with_custom_fields(jid:to_binary(RoomJID), AliceBin, Name2, Subject2, Config, Opts2),
 1204:     %% It overwrites old config for all fields
 1205:     Opts3 = [% #{<<"key">> => <<"background">>, <<"value">> => <<"red">>},
 1206:              #{<<"key">> => <<"music">>, <<"value">> => <<"sad">>},
 1207:              #{<<"key">> => <<"roomname">>, <<"value">> => Name2},
 1208:              #{<<"key">> => <<"subject">>, <<"value">> => Subject2}],
 1209:     ?assertMatch(#{<<"name">> := Name2, <<"subject">> := Subject2, <<"options">> := Opts3},
 1210:                  get_ok_value(?CHANGE_CONFIG_PATH, Res2)).
 1211: 
 1212: admin_change_room_config_errors(Config) ->
 1213:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}, {kate, 1}],
 1214:                                     fun admin_change_room_config_errors_story/4).
 1215: 
 1216: admin_change_room_config_errors_story(Config, Alice, Bob, Kate) ->
 1217:     AliceBin = escalus_client:short_jid(Alice),
 1218:     BobBin = escalus_client:short_jid(Bob),
 1219:     MUCServer = ?config(muc_light_host, Config),
 1220:     RoomName = <<"first room">>,
 1221:     {ok, #{jid := RoomJID}} = create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
 1222:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
 1223:     % Try to change the config of the non-existent room
 1224:     Res = change_room_configuration(
 1225:              make_bare_jid(<<"unknown">>, MUCServer), AliceBin, RoomName, <<"subject2">>, Config),
 1226:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res), <<"not found">>)),
 1227:     % Try to change the config by the non-existent user
 1228:     Res2 = change_room_configuration(
 1229:              jid:to_binary(RoomJID), <<"wrong-user@wrong-domain">>, RoomName, <<"subject2">>,
 1230:              Config),
 1231:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"User's domain does not exist">>)),
 1232:     % Try to change a config by the user without permission
 1233:     Res3 = change_room_configuration(
 1234:              jid:to_binary(RoomJID), BobBin, RoomName, <<"subject2">>, Config),
 1235:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res3),
 1236:                                           <<"does not have permission to change">>)),
 1237:     % Try to change a config by a user not occupying the room
 1238:     KateBin = escalus_client:short_jid(Kate),
 1239:     Res4 = change_room_configuration(
 1240:              jid:to_binary(RoomJID), KateBin, RoomName, <<"subject2">>, Config),
 1241:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res4), <<"does not occupy">>)).
 1242: 
 1243: admin_change_room_config_non_existent_domain(Config) ->
 1244:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
 1245:                                     fun admin_change_room_config_non_existent_domain_story/3).
 1246: 
 1247: admin_change_room_config_non_existent_domain_story(Config, Alice, Bob) ->
 1248:     AliceBin = escalus_client:short_jid(Alice),
 1249:     BobBin = escalus_client:short_jid(Bob),
 1250:     MUCServer = ?config(muc_light_host, Config),
 1251:     RoomName = <<"first room">>,
 1252:     {ok, #{jid := #jid{luser = RoomID} = RoomJID}} =
 1253:         create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
 1254:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
 1255:     Res = change_room_configuration(
 1256:             make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), AliceBin, RoomName, <<"subject2">>, Config),
 1257:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res), <<"not found">>)).
 1258: 
 1259: admin_invite_user(Config) ->
 1260:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}], fun admin_invite_user_story/3).
 1261: 
 1262: admin_invite_user_story(Config, Alice, Bob) ->
 1263:     AliceBin = escalus_client:short_jid(Alice),
 1264:     BobBin = escalus_client:short_jid(Bob),
 1265:     Domain = escalus_client:server(Alice),
 1266:     MUCServer = ?config(muc_light_host, Config),
 1267:     Name = <<"first room">>,
 1268:     {ok, #{jid := RoomJID}} = create_room(MUCServer, Name, <<"subject2">>, AliceBin),
 1269: 
 1270:     Res = invite_user(jid:to_binary(RoomJID), AliceBin, BobBin, Config),
 1271:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?INVITE_USER_PATH, Res),
 1272:                                           <<"successfully">>)),
 1273:     BobName = escalus_utils:jid_to_lower(escalus_client:username(Bob)),
 1274:     AliceName = escalus_utils:jid_to_lower(escalus_client:username(Alice)),
 1275:     ExpectedAff = lists:sort([{{AliceName, Domain}, owner},
 1276:                               {{BobName, Domain}, member}]),
 1277:     ?assertMatch(ExpectedAff, lists:sort(get_room_aff(RoomJID))).
 1278: 
 1279: admin_invite_user_errors(Config) ->
 1280:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
 1281:                                     fun admin_invite_user_errors_story/3).
 1282: 
 1283: admin_invite_user_errors_story(Config, Alice, Bob) ->
 1284:     AliceBin = escalus_client:short_jid(Alice),
 1285:     BobBin = escalus_client:short_jid(Bob),
 1286:     MUCServer = ?config(muc_light_host, Config),
 1287:     {ok, #{jid := #jid{luser = RoomID} = RoomJID}} =
 1288:         create_room(MUCServer, <<"first room">>, <<"subject">>, AliceBin),
 1289:     % Try to invite a user to not existing room
 1290:     Res = invite_user(make_bare_jid(?UNKNOWN, MUCServer), AliceBin, BobBin, Config),
 1291:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res), <<"not found">>)),
 1292:     % User without rooms tries to invite a user
 1293:     Res2 = invite_user(jid:to_binary(RoomJID), BobBin, AliceBin, Config),
 1294:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"does not occupy this room">>)),
 1295:     % Try with a non-existent domain
 1296:     Res3 = invite_user(make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), AliceBin, BobBin, Config),
 1297:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res3), <<"not found">>)).
 1298: 
 1299: admin_delete_room(Config) ->
 1300:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun admin_delete_room_story/2).
 1301: 
 1302: admin_delete_room_story(Config, Alice) ->
 1303:     AliceBin = escalus_client:short_jid(Alice),
 1304:     MUCServer = ?config(muc_light_host, Config),
 1305:     Name = <<"first room">>,
 1306:     {ok, #{jid := RoomJID} = RoomInfo} = create_room(MUCServer, Name, <<"subject">>, AliceBin),
 1307:     Res = delete_room(jid:to_binary(RoomJID), Config),
 1308:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?DELETE_ROOM_PATH, Res),
 1309:                                           <<"successfully">>)),
 1310:     ?assertEqual({error, not_exists}, get_room_info(RoomJID), RoomInfo),
 1311:     % Try with a non-existent room
 1312:     Res2 = delete_room(make_bare_jid(?UNKNOWN, MUCServer), Config),
 1313:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"not found">>)).
 1314: 
 1315: admin_delete_room_non_existent_domain(Config) ->
 1316:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1317:                                     fun admin_delete_room_non_existent_domain_story/2).
 1318: 
 1319: admin_delete_room_non_existent_domain_story(Config, Alice) ->
 1320:     AliceBin = escalus_client:short_jid(Alice),
 1321:     MUCServer = ?config(muc_light_host, Config),
 1322:     Name = <<"first room">>,
 1323:     {ok, #{jid := #jid{luser = RoomID}}} =
 1324:         create_room(MUCServer, Name, <<"subject">>, AliceBin),
 1325:     Res = delete_room(make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), Config),
 1326:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res), <<"not found">>)).
 1327: 
 1328: admin_kick_user(Config) ->
 1329:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}], fun admin_kick_user_story/3).
 1330: 
 1331: admin_kick_user_story(Config, Alice, Bob) ->
 1332:     AliceBin = escalus_client:short_jid(Alice),
 1333:     BobBin = escalus_client:short_jid(Bob),
 1334:     MUCServer = ?config(muc_light_host, Config),
 1335:     RoomName = <<"first room">>,
 1336:     {ok, #{jid := RoomJID}} = create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
 1337:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
 1338:     ?assertEqual(2, length(get_room_aff(RoomJID))),
 1339:     Res = kick_user(jid:to_binary(RoomJID), BobBin, Config),
 1340:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?KICK_USER_PATH, Res),
 1341:                                           <<"successfully">>)),
 1342:     ?assertEqual(1, length(get_room_aff(RoomJID))).
 1343: 
 1344: admin_send_message_to_room(Config) ->
 1345:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
 1346:                                     fun admin_send_message_to_room_story/3).
 1347: 
 1348: admin_send_message_to_room_story(Config, Alice, Bob) ->
 1349:     AliceBin = escalus_client:short_jid(Alice),
 1350:     BobBin = escalus_client:short_jid(Bob),
 1351:     MUCServer = ?config(muc_light_host, Config),
 1352:     RoomName = <<"first room">>,
 1353:     MsgBody = <<"Hello there!">>,
 1354:     {ok, #{jid := RoomJID}} = create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
 1355:     {ok, _} = invite_user(RoomJID, AliceBin, BobBin),
 1356:     Res = send_message_to_room(jid:to_binary(RoomJID), AliceBin, MsgBody, Config),
 1357:     ?assertNotEqual(nomatch, binary:match(get_ok_value(?SEND_MESSAGE_PATH, Res),
 1358:                                           <<"successfully">>)),
 1359:     [_, Msg] = escalus:wait_for_stanzas(Bob, 2),
 1360:     escalus:assert(is_message, Msg).
 1361: 
 1362: admin_send_message_to_room_errors(Config) ->
 1363:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
 1364:                                     fun admin_send_message_to_room_errors_story/3).
 1365: 
 1366: admin_send_message_to_room_errors_story(Config, Alice, Bob) ->
 1367:     AliceBin = escalus_client:short_jid(Alice),
 1368:     BobBin = escalus_client:short_jid(Bob),
 1369:     MUCServer = ?config(muc_light_host, Config),
 1370:     MsgBody = <<"Hello there!">>,
 1371:     {ok, #{jid := #jid{luser = ARoomID} = ARoomJID}} =
 1372:         create_room(MUCServer, <<"alice room">>, <<"subject">>, AliceBin),
 1373:     % Try with a non-existent domain
 1374:     Res2 = send_message_to_room(make_bare_jid(ARoomID, ?UNKNOWN_DOMAIN), AliceBin, MsgBody, Config),
 1375:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"not found">>)),
 1376:     % Try with a user without rooms
 1377:     Res3 = send_message_to_room(jid:to_binary(ARoomJID), BobBin, MsgBody, Config),
 1378:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res3), <<"does not occupy this room">>)),
 1379:     % Try with a room not occupied by this user
 1380:     {ok, #{jid := _RoomJID2}} = create_room(MUCServer, <<"bob room">>, <<"subject">>, BobBin),
 1381:     Res4 = send_message_to_room(jid:to_binary(ARoomJID), BobBin, MsgBody, Config),
 1382:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res4), <<"does not occupy this room">>)).
 1383: 
 1384: admin_get_room_messages(Config) ->
 1385:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun admin_get_room_messages_story/2).
 1386: 
 1387: admin_get_room_messages_story(Config, Alice) ->
 1388:     AliceBin = escalus_client:short_jid(Alice),
 1389:     %Domain = escalus_client:server(Alice),
 1390:     MUCServer = ?config(muc_light_host, Config),
 1391:     RoomName = <<"first room">>,
 1392:     RoomName2 = <<"second room">>,
 1393:     {ok, #{jid := #jid{luser = RoomID} = RoomJID}} =
 1394:         create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
 1395:     {ok, _} = create_room(MUCServer, RoomName2, <<"subject">>, AliceBin),
 1396:     Message = <<"Hello friends">>,
 1397:     send_message_to_room(RoomJID, jid:from_binary(AliceBin), Message),
 1398:     mam_helper:wait_for_room_archive_size(MUCServer, RoomID, 1),
 1399:     % Get messages so far
 1400:     Limit = 40,
 1401:     Res = get_room_messages(jid:to_binary(RoomJID), Limit, null, Config),
 1402:     #{<<"stanzas">> := [#{<<"stanza">> := StanzaXML}], <<"limit">> := Limit} =
 1403:         get_ok_value(?GET_MESSAGES_PATH, Res),
 1404:     ?assertMatch({ok, #xmlel{name = <<"message">>}}, exml:parse(StanzaXML)),
 1405:     % Get messages before the given date and time
 1406:     Before = <<"2022-02-17T04:54:13+00:00">>,
 1407:     Res2 = get_room_messages(jid:to_binary(RoomJID), null, Before, Config),
 1408:     ?assertMatch(#{<<"stanzas">> := [], <<"limit">> := 50}, get_ok_value(?GET_MESSAGES_PATH, Res2)),
 1409:     % Try to pass too big page size value
 1410:     Res3 = get_room_messages(jid:to_binary(RoomJID), 51, Before, Config),
 1411:     ?assertMatch(#{<<"limit">> := 50}, get_ok_value(?GET_MESSAGES_PATH, Res3)),
 1412:     % Try with a non-existent room
 1413:     Res4 = get_room_messages(make_bare_jid(<<"badroom">>, MUCServer), null, null, Config),
 1414:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res4), <<"Room not found">>)).
 1415: 
 1416: admin_get_room_messages_non_existent_domain(Config) ->
 1417:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1418:                                     fun admin_get_room_messages_non_existent_domain_story/2).
 1419: 
 1420: admin_get_room_messages_non_existent_domain_story(Config, Alice) ->
 1421:     AliceBin = escalus_client:short_jid(Alice),
 1422:     MUCServer = ?config(muc_light_host, Config),
 1423:     RoomName = <<"first room">>,
 1424:     {ok, #{jid := #jid{luser = RoomID}}} =
 1425:     create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
 1426:     Limit = 40,
 1427:     Res = get_room_messages(make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), Limit, null, Config),
 1428:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res), <<"not found">>)).
 1429: 
 1430: admin_list_user_rooms(Config) ->
 1431:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun admin_list_user_rooms_story/2).
 1432: 
 1433: admin_list_user_rooms_story(Config, Alice) ->
 1434:     AliceBin = escalus_client:short_jid(Alice),
 1435:     Domain = escalus_client:server(Alice),
 1436:     MUCServer = ?config(muc_light_host, Config),
 1437:     RoomName = <<"first room">>,
 1438:     RoomName2 = <<"second room">>,
 1439:     {ok, #{jid := RoomJID}} = create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
 1440:     {ok, #{jid := RoomJID2}} = create_room(MUCServer, RoomName2, <<"subject">>, AliceBin),
 1441:     Res = list_user_rooms(AliceBin, Config),
 1442:     ?assertEqual(lists:sort([jid:to_binary(RoomJID), jid:to_binary(RoomJID2)]),
 1443:                  lists:sort(get_ok_value(?LIST_USER_ROOMS_PATH, Res))),
 1444:     % Try with a non-existent user
 1445:     Res2 = list_user_rooms(<<"not-exist@", Domain/binary>>, Config),
 1446:     ?assertMatch({_, _}, binary:match(get_err_msg(Res2), <<"does not exist">>)).
 1447: 
 1448: admin_list_user_rooms_non_existent_domain(Config) ->
 1449:     Res = list_user_rooms(<<"not-exist@not-exist">>, Config),
 1450:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res), <<"does not exist">>)).
 1451: 
 1452: admin_list_room_users(Config) ->
 1453:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun admin_list_room_users_story/2).
 1454: 
 1455: admin_list_room_users_story(Config, Alice) ->
 1456:     AliceBin = escalus_client:short_jid(Alice),
 1457:     AliceLower = escalus_utils:jid_to_lower(AliceBin),
 1458:     MUCServer = ?config(muc_light_host, Config),
 1459:     RoomName = <<"first room">>,
 1460:     {ok, #{jid := RoomJID}} = create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
 1461:     Res = list_room_users(jid:to_binary(RoomJID), Config),
 1462:     ?assertEqual([#{<<"jid">> => AliceLower, <<"affiliation">> => <<"OWNER">>}],
 1463:                  get_ok_value(?LIST_ROOM_USERS_PATH, Res)),
 1464:     % Try with a non-existent room
 1465:     Res2 = list_room_users(make_bare_jid(?UNKNOWN, MUCServer), Config),
 1466:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"not found">>)).
 1467: 
 1468: admin_list_room_users_non_existent_domain(Config) ->
 1469:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1470:                                     fun admin_list_room_users_non_existent_domain_story/2).
 1471: 
 1472: admin_list_room_users_non_existent_domain_story(Config, Alice) ->
 1473:     AliceBin = escalus_client:short_jid(Alice),
 1474:     MUCServer = ?config(muc_light_host, Config),
 1475:     RoomName = <<"first room">>,
 1476:     {ok, #{jid := RoomJID}} = create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
 1477:     Res = list_room_users(make_bare_jid(RoomJID#jid.luser, ?UNKNOWN_DOMAIN), Config),
 1478:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res), <<"not found">>)).
 1479: 
 1480: admin_get_room_config(Config) ->
 1481:     escalus:fresh_story_with_config(Config, [{alice, 1}], fun admin_get_room_config_story/2).
 1482: 
 1483: admin_get_room_config_story(Config, Alice) ->
 1484:     AliceBin = escalus_client:short_jid(Alice),
 1485:     AliceLower = escalus_utils:jid_to_lower(AliceBin),
 1486:     MUCServer = ?config(muc_light_host, Config),
 1487:     RoomName = <<"first room">>,
 1488:     RoomSubject = <<"Room about nothing">>,
 1489:     {ok, #{jid := #jid{luser = _RoomID} = RoomJID}} =
 1490:         create_room(MUCServer, RoomName, RoomSubject, AliceBin),
 1491:     RoomJIDBin = jid:to_binary(RoomJID),
 1492:     Res = get_room_config(RoomJIDBin, Config),
 1493:     ?assertEqual(#{<<"jid">> => RoomJIDBin, <<"subject">> => RoomSubject, <<"name">> => RoomName,
 1494:                     <<"options">> => [#{<<"key">> => <<"background">>, <<"value">> => <<>>},
 1495:                                       #{<<"key">> => <<"music">>, <<"value">> => <<>>},
 1496:                                       #{<<"key">> => <<"roomname">>, <<"value">> => RoomName},
 1497:                                       #{<<"key">> => <<"subject">>, <<"value">> => RoomSubject}],
 1498:                     <<"participants">> => [#{<<"jid">> => AliceLower,
 1499:                                              <<"affiliation">> => <<"OWNER">>}]},
 1500:                  get_ok_value([data, muc_light, getRoomConfig], Res)),
 1501:     % Try with a non-existent room
 1502:     Res2 = get_room_config(make_bare_jid(?UNKNOWN, MUCServer), Config),
 1503:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res2), <<"not found">>)).
 1504: 
 1505: admin_get_room_config_non_existent_domain(Config) ->
 1506:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1507:                                     fun admin_get_room_config_non_existent_domain_story/2).
 1508: 
 1509: admin_get_room_config_non_existent_domain_story(Config, Alice) ->
 1510:     AliceBin = escalus_client:short_jid(Alice),
 1511:     MUCServer = ?config(muc_light_host, Config),
 1512:     RoomName = <<"first room">>,
 1513:     {ok, #{jid := #jid{luser = RoomID}}} =
 1514:         create_room(MUCServer, RoomName, <<"subject">>, AliceBin),
 1515:     Res = get_room_config(make_bare_jid(RoomID, ?UNKNOWN_DOMAIN), Config),
 1516:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res), <<"not found">>)).
 1517: 
 1518: %% User mod_muc_light not configured test cases
 1519: user_create_room_muc_light_not_configured(Config) ->
 1520:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1521:         fun user_create_room_muc_light_not_configured_story/2).
 1522: 
 1523: user_create_room_muc_light_not_configured_story(Config, Alice) ->
 1524:     MucServer = ?config(muc_light_host, Config),
 1525:     Name = <<"first room">>,
 1526:     Subject = <<"testing">>,
 1527:     Res = user_create_room(Alice, MucServer, Name, Subject, null, Config),
 1528:     ?assertEqual(<<"muc_server_not_found">>, get_err_code(Res)).
 1529: 
 1530: user_change_room_config_muc_light_not_configured(Config) ->
 1531:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1532:         fun user_change_room_config_muc_light_not_configured_story/2).
 1533: 
 1534: user_change_room_config_muc_light_not_configured_story(Config, Alice) ->
 1535:     Name = <<"changed room">>,
 1536:     Subject = <<"not testing">>,
 1537:     Res = user_change_room_configuration(Alice, get_room_name(), Name, Subject, Config),
 1538:     get_not_loaded(Res).
 1539: 
 1540: user_invite_user_muc_light_not_configured(Config) ->
 1541:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
 1542:         fun user_invite_user_muc_light_not_configured_story/3).
 1543: 
 1544: user_invite_user_muc_light_not_configured_story(Config, Alice, Bob) ->
 1545:     BobBin = escalus_client:short_jid(Bob),
 1546:     Res = user_invite_user(Alice, get_room_name(), BobBin, Config),
 1547:     get_not_loaded(Res).
 1548: 
 1549: user_delete_room_muc_light_not_configured(Config) ->
 1550:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1551:         fun user_delete_room_muc_light_not_configured_story/2).
 1552: 
 1553: user_delete_room_muc_light_not_configured_story(Config, Alice) ->
 1554:     Res = user_delete_room(Alice, get_room_name(), Config),
 1555:     get_not_loaded(Res).
 1556: 
 1557: user_kick_user_muc_light_not_configured(Config) ->
 1558:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1559:         fun user_kick_user_muc_light_not_configured_story/2).
 1560: 
 1561: user_kick_user_muc_light_not_configured_story(Config, Alice) ->
 1562:     Res = user_kick_user(Alice, get_room_name(), null, Config),
 1563:     get_not_loaded(Res).
 1564: 
 1565: user_send_message_to_room_muc_light_not_configured(Config) ->
 1566:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1567:         fun user_send_message_to_room_muc_light_not_configured_story/2).
 1568: 
 1569: user_send_message_to_room_muc_light_not_configured_story(Config, Alice) ->
 1570:     MsgBody = <<"Hello there!">>,
 1571:     Res = user_send_message_to_room(Alice, get_room_name(), MsgBody, Config),
 1572:     get_not_loaded(Res).
 1573: 
 1574: user_get_room_messages_muc_light_or_mam_not_configured(Config) ->
 1575:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1576:         fun user_get_room_messages_muc_light_or_mam_not_configured_story/2).
 1577: 
 1578: user_get_room_messages_muc_light_or_mam_not_configured_story(Config, Alice) ->
 1579:     Before = <<"2022-02-17T04:54:13+00:00">>,
 1580:     Res = user_get_room_messages(Alice, get_room_name(), 51, Before, Config),
 1581:     get_not_loaded(Res).
 1582: 
 1583: user_list_rooms_muc_light_not_configured(Config) ->
 1584:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1585:         fun user_list_rooms_muc_light_not_configured_story/2).
 1586: 
 1587: user_list_rooms_muc_light_not_configured_story(Config, Alice) ->
 1588:     Res = user_list_rooms(Alice, Config),
 1589:     get_not_loaded(Res).
 1590: 
 1591: user_list_room_users_muc_light_not_configured(Config) ->
 1592:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1593:         fun user_list_room_users_muc_light_not_configured_story/2).
 1594: 
 1595: user_list_room_users_muc_light_not_configured_story(Config, Alice) ->
 1596:     Res = user_list_room_users(Alice, get_room_name(), Config),
 1597:     get_not_loaded(Res).
 1598: 
 1599: user_get_room_config_muc_light_not_configured(Config) ->
 1600:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1601:         fun user_get_room_config_muc_light_not_configured_story/2).
 1602: 
 1603: user_get_room_config_muc_light_not_configured_story(Config, Alice) ->
 1604:     Res = user_get_room_config(Alice, get_room_name(), Config),
 1605:     get_not_loaded(Res).
 1606: 
 1607: user_blocking_list_muc_light_not_configured(Config) ->
 1608:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
 1609:          fun user_blocking_list_muc_light_not_configured_story/3).
 1610: 
 1611: user_blocking_list_muc_light_not_configured_story(Config, Alice, Bob) ->
 1612:     BobBin = escalus_client:full_jid(Bob),
 1613:     Res = user_get_blocking(Alice, Config),
 1614:     get_not_loaded(Res),
 1615:     Res2 = user_set_blocking(Alice, [{<<"USER">>, <<"DENY">>, BobBin}], Config),
 1616:     get_not_loaded(Res2).
 1617: 
 1618: %% Admin mod_muc_light not configured test cases
 1619: 
 1620: admin_create_room_muc_light_not_configured(Config) ->
 1621:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1622:         fun admin_create_room_muc_light_not_configured_story/2).
 1623: 
 1624: admin_create_room_muc_light_not_configured_story(Config, Alice) ->
 1625:     AliceBin = escalus_client:short_jid(Alice),
 1626:     MucServer = ?config(muc_light_host, Config),
 1627:     Name = <<"first room">>,
 1628:     Subject = <<"testing">>,
 1629:     Res = create_room(MucServer, Name, AliceBin, Subject, null, Config),
 1630:     ?assertEqual(<<"muc_server_not_found">>, get_err_code(Res)).
 1631: 
 1632: admin_invite_user_muc_light_not_configured(Config) ->
 1633:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
 1634:         fun admin_invite_user_muc_light_not_configured_story/3).
 1635: 
 1636: admin_invite_user_muc_light_not_configured_story(Config, Alice, Bob) ->
 1637:     AliceBin = escalus_client:short_jid(Alice),
 1638:     BobBin = escalus_client:short_jid(Bob),
 1639:     Res = invite_user(get_room_name(), AliceBin, BobBin, Config),
 1640:     get_not_loaded(Res).
 1641: 
 1642: admin_change_room_config_muc_light_not_configured(Config) ->
 1643:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1644:         fun admin_change_room_config_muc_light_not_configured_story/2).
 1645: 
 1646: admin_change_room_config_muc_light_not_configured_story(Config, Alice) ->
 1647:     AliceBin = escalus_client:short_jid(Alice),
 1648:     Name = <<"changed room">>,
 1649:     Subject = <<"not testing">>,
 1650:     Res = change_room_configuration(get_room_name(), AliceBin, Name, Subject, Config),
 1651:     get_not_loaded(Res).
 1652: 
 1653: admin_delete_room_muc_light_not_configured(Config) ->
 1654:     Res = delete_room(get_room_name(), Config),
 1655:     get_not_loaded(Res).
 1656: 
 1657: admin_kick_user_muc_light_not_configured(Config) ->
 1658:     escalus:fresh_story_with_config(Config, [{bob, 1}],
 1659:         fun admin_kick_user_muc_light_not_configured_story/2).
 1660: 
 1661: admin_kick_user_muc_light_not_configured_story(Config, Bob) ->
 1662:     BobBin = escalus_client:short_jid(Bob),
 1663:     Res = kick_user(get_room_name(), BobBin, Config),
 1664:     get_not_loaded(Res).
 1665: 
 1666: admin_send_message_to_room_muc_light_not_configured(Config) ->
 1667:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1668:         fun admin_send_message_to_room_muc_light_not_configured_story/2).
 1669: 
 1670: admin_send_message_to_room_muc_light_not_configured_story(Config, Alice) ->
 1671:     AliceBin = escalus_client:short_jid(Alice),
 1672:     MsgBody = <<"Hello there!">>,
 1673:     Res = send_message_to_room(get_room_name(), AliceBin, MsgBody, Config),
 1674:     get_not_loaded(Res).
 1675: 
 1676: admin_get_room_messages_muc_light_or_mam_not_configured(Config) ->
 1677:     Limit = 40,
 1678:     Res = get_room_messages(get_room_name(), Limit, null, Config),
 1679:     get_not_loaded(Res).
 1680: 
 1681: admin_list_user_rooms_muc_light_not_configured(Config) ->
 1682:     escalus:fresh_story_with_config(Config, [{alice, 1}],
 1683:         fun admin_list_user_rooms_muc_light_not_configured_story/2).
 1684: 
 1685: admin_list_user_rooms_muc_light_not_configured_story(Config, Alice) ->
 1686:     AliceBin = escalus_client:short_jid(Alice),
 1687:     Res = list_user_rooms(AliceBin, Config),
 1688:     get_not_loaded(Res).
 1689: 
 1690: admin_list_room_users_muc_light_not_configured(Config) ->
 1691:     Res = list_room_users(get_room_name(), Config),
 1692:     get_not_loaded(Res).
 1693: 
 1694: admin_get_room_config_muc_light_not_configured(Config) ->
 1695:     Res = get_room_config(get_room_name(), Config),
 1696:     get_not_loaded(Res).
 1697: 
 1698: %% Helpers
 1699: 
 1700: get_room_name() ->
 1701:     Domain = domain_helper:domain(),
 1702:     <<"NON_EXISTING@", Domain/binary>>.
 1703: 
 1704: admin_blocking_list_muc_light_not_configured(Config) ->
 1705:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
 1706:         fun admin_blocking_list_muc_light_not_configured_story/3).
 1707: 
 1708: admin_blocking_list_muc_light_not_configured_story(Config, Alice, Bob) ->
 1709:     AliceBin = escalus_client:full_jid(Alice),
 1710:     BobBin = escalus_client:full_jid(Bob),
 1711:     Res = get_user_blocking(AliceBin, Config),
 1712:     get_not_loaded(Res),
 1713:     Res2 = set_blocking(AliceBin, [{<<"USER">>, <<"DENY">>, BobBin}], Config),
 1714:     get_not_loaded(Res2).
 1715: 
 1716: make_bare_jid(User, Server) ->
 1717:     JID = jid:make_bare(User, Server),
 1718:     jid:to_binary(JID).
 1719: 
 1720: send_message_to_room(RoomJID, SenderJID, Message) ->
 1721:     rpc(mim(), mod_muc_light_api, send_message, [RoomJID, SenderJID, Message]).
 1722: 
 1723: get_room_messages(ID, Domain) ->
 1724:     {ok, Messages} = rpc(mim(), mod_muc_light_api, get_room_messages, [Domain, ID]),
 1725:     Messages.
 1726: 
 1727: create_room(Domain, Name, Subject, CreatorBin) ->
 1728:     CreatorJID = jid:from_binary(CreatorBin),
 1729:     Config = #{<<"roomname">> => Name, <<"subject">> => Subject},
 1730:     rpc(mim(), mod_muc_light_api, create_room, [Domain, CreatorJID, Config]).
 1731: 
 1732: invite_user(RoomJID, SenderBin, RecipientBin) ->
 1733:     SenderJID = jid:from_binary(SenderBin),
 1734:     RecipientJID = jid:from_binary(RecipientBin),
 1735:     rpc(mim(), mod_muc_light_api, invite_to_room, [RoomJID, SenderJID, RecipientJID]).
 1736: 
 1737: get_room_info(error) ->
 1738:     arg_is_not_jid;
 1739: get_room_info(#jid{} = JID) ->
 1740:     HostType = domain_helper:host_type(),
 1741:     RoomUS = jid:to_lus(JID),
 1742:     rpc(mim(), mod_muc_light_db_backend, get_info, [HostType, RoomUS]).
 1743: 
 1744: get_room_aff(JID) ->
 1745:     {ok, _, Aff, _} = get_room_info(JID),
 1746:     Aff.
 1747: 
 1748: prepare_blocking_items_for_query(Items) ->
 1749:     [#{<<"entity">> => Who, <<"entityType">> => What,
 1750:        <<"action">> => Action} || {What, Action, Who} <- Items].
 1751: 
 1752: %% Commands
 1753: 
 1754: create_room(MUCDomain, Name, Owner, Subject, Id, Config) ->
 1755:     Vars = #{<<"mucDomain">> => MUCDomain, <<"name">> => Name, <<"owner">> => Owner,
 1756:              <<"subject">> => Subject, <<"id">> => Id},
 1757:     execute_command(<<"muc_light">>, <<"createRoom">>, Vars, Config).
 1758: 
 1759: create_room_with_custom_fields(MUCDomain, Name, Owner, Subject,
 1760:                                Id, Config, CustomFields) ->
 1761:     Vars = #{<<"mucDomain">> => MUCDomain, <<"name">> => Name, <<"owner">> => Owner,
 1762:              <<"subject">> => Subject, <<"id">> => Id,
 1763:              <<"options">> => format_options(CustomFields)},
 1764:     execute_command(<<"muc_light">>, <<"createRoom">>, Vars, Config).
 1765: 
 1766: change_room_configuration(RoomJID, OwnerJID, Name, Subject, Config) ->
 1767:     Vars = #{<<"room">> => RoomJID, <<"name">> => Name, <<"owner">> => OwnerJID,
 1768:              <<"subject">> => Subject},
 1769:     execute_command(<<"muc_light">>, <<"changeRoomConfiguration">>, Vars, Config).
 1770: 
 1771: change_room_configuration_with_custom_fields(RoomJID, OwnerJID, Name, Subject, Config, Opts) ->
 1772:     Vars = #{<<"room">> => RoomJID, <<"name">> => Name, <<"owner">> => OwnerJID,
 1773:              <<"subject">> => Subject, <<"options">> => format_options(Opts)},
 1774:     execute_command(<<"muc_light">>, <<"changeRoomConfiguration">>, Vars, Config).
 1775: 
 1776: invite_user(RoomJID, Sender, Recipient, Config) ->
 1777:     Vars = #{<<"room">> => RoomJID, <<"sender">> => Sender, <<"recipient">> => Recipient},
 1778:     execute_command(<<"muc_light">>, <<"inviteUser">>, Vars, Config).
 1779: 
 1780: kick_user(RoomJID, User, Config) ->
 1781:     Vars = #{<<"room">> => RoomJID, <<"user">> => User},
 1782:     execute_command(<<"muc_light">>, <<"kickUser">>, Vars, Config).
 1783: 
 1784: send_message_to_room(RoomJID, From, Body, Config) ->
 1785:     Vars = #{<<"room">> => RoomJID, <<"from">> => From, <<"body">> => Body},
 1786:     execute_command(<<"muc_light">>, <<"sendMessageToRoom">>, Vars, Config).
 1787: 
 1788: list_user_rooms(User, Config) ->
 1789:     Vars = #{<<"user">> => User},
 1790:     execute_command(<<"muc_light">>, <<"listUserRooms">>, Vars, Config).
 1791: 
 1792: delete_room(RoomJID, Config) ->
 1793:     Vars = #{<<"room">> => RoomJID},
 1794:     execute_command(<<"muc_light">>, <<"deleteRoom">>, Vars, Config).
 1795: 
 1796: get_room_messages(RoomJID, PageSize, Before, Config) ->
 1797:     Vars = #{<<"room">> => RoomJID, <<"pageSize">> => PageSize, <<"before">> => Before},
 1798:     execute_command(<<"muc_light">>, <<"getRoomMessages">>, Vars, Config).
 1799: 
 1800: list_room_users(RoomJID, Config) ->
 1801:     Vars = #{<<"room">> => RoomJID},
 1802:     execute_command(<<"muc_light">>, <<"listRoomUsers">>, Vars, Config).
 1803: 
 1804: get_room_config(RoomJID, Config) ->
 1805:     Vars = #{<<"room">> => RoomJID},
 1806:     execute_command(<<"muc_light">>, <<"getRoomConfig">>, Vars, Config).
 1807: 
 1808: get_user_blocking(UserJID, Config) ->
 1809:     Vars = #{<<"user">> => UserJID},
 1810:     execute_command(<<"muc_light">>, <<"getBlockingList">>, Vars, Config).
 1811: 
 1812: set_blocking(UserJID, Items, Config) ->
 1813:     Vars = #{<<"user">> => UserJID, <<"items">> => prepare_blocking_items_for_query(Items)},
 1814:     execute_command(<<"muc_light">>, <<"setBlockingList">>, Vars, Config).
 1815: 
 1816: user_create_room(User, MUCDomain, Name, Subject, Id, Config) ->
 1817:     Vars = #{<<"mucDomain">> => MUCDomain, <<"name">> => Name, <<"subject">> => Subject,
 1818:              <<"id">> => Id},
 1819:     execute_user_command(<<"muc_light">>, <<"createRoom">>, User, Vars, Config).
 1820: 
 1821: user_create_room_with_options(User, MUCDomain, Name, Subject, Id, CustomFields, Config) ->
 1822:     Vars = #{<<"mucDomain">> => MUCDomain, <<"name">> => Name, <<"subject">> => Subject,
 1823:              <<"id">> => Id, <<"options">> => format_options(CustomFields)},
 1824:     execute_user_command(<<"muc_light">>, <<"createRoom">>, User, Vars, Config).
 1825: 
 1826: user_change_room_configuration(User, RoomJID, Name, Subject, Config) ->
 1827:     Vars = #{<<"room">> => RoomJID, <<"name">> => Name, <<"subject">> => Subject},
 1828:     execute_user_command(<<"muc_light">>, <<"changeRoomConfiguration">>, User, Vars, Config).
 1829: 
 1830: user_change_room_configuration_with_custom_fields(User, RoomJID, Name, Subject, Config, Options) ->
 1831:     Vars = #{<<"room">> => RoomJID, <<"name">> => Name, <<"subject">> => Subject,
 1832:              <<"options">> => format_options(Options)},
 1833:     execute_user_command(<<"muc_light">>, <<"changeRoomConfiguration">>, User, Vars, Config).
 1834: 
 1835: format_options(Map) ->
 1836:     [#{<<"key">> => K, <<"value">> => V} || {K, V} <- maps:to_list(Map)].
 1837: 
 1838: user_invite_user(User, RoomJID, Recipient, Config) ->
 1839:     Vars = #{<<"room">> => RoomJID, <<"recipient">> => Recipient},
 1840:     execute_user_command(<<"muc_light">>, <<"inviteUser">>, User, Vars, Config).
 1841: 
 1842: user_delete_room(User, RoomJID, Config) ->
 1843:     Vars = #{<<"room">> => RoomJID},
 1844:     execute_user_command(<<"muc_light">>, <<"deleteRoom">>, User, Vars, Config).
 1845: 
 1846: user_kick_user(User, RoomJID, QueriedUser, Config) ->
 1847:     Vars = #{<<"room">> => RoomJID, <<"user">> => QueriedUser},
 1848:     execute_user_command(<<"muc_light">>, <<"kickUser">>, User, Vars, Config).
 1849: 
 1850: user_send_message_to_room(User, RoomJID, Body, Config) ->
 1851:     Vars = #{<<"room">> => RoomJID, <<"body">> => Body},
 1852:     execute_user_command(<<"muc_light">>, <<"sendMessageToRoom">>, User, Vars, Config).
 1853: 
 1854: user_get_room_messages(User, RoomJID, PageSize, Before, Config) ->
 1855:     Vars = #{<<"room">> => RoomJID, <<"pageSize">> => PageSize, <<"before">> => Before},
 1856:     execute_user_command(<<"muc_light">>, <<"getRoomMessages">>, User, Vars, Config).
 1857: 
 1858: user_list_rooms(User, Config) ->
 1859:     execute_user_command(<<"muc_light">>, <<"listRooms">>, User, #{}, Config).
 1860: 
 1861: user_list_room_users(User, RoomJID, Config) ->
 1862:     Vars = #{<<"room">> => RoomJID},
 1863:     execute_user_command(<<"muc_light">>, <<"listRoomUsers">>, User, Vars, Config).
 1864: 
 1865: user_get_room_config(User, RoomJID, Config) ->
 1866:     Vars = #{<<"room">> => RoomJID},
 1867:     execute_user_command(<<"muc_light">>, <<"getRoomConfig">>, User, Vars, Config).
 1868: 
 1869: user_get_blocking(User, Config) ->
 1870:     execute_user_command(<<"muc_light">>, <<"getBlockingList">>, User, #{}, Config).
 1871: 
 1872: user_set_blocking(User, Items, Config) ->
 1873:     Vars = #{<<"items">> => prepare_blocking_items_for_query(Items)},
 1874:     execute_user_command(<<"muc_light">>, <<"setBlockingList">>, User, Vars, Config).
 1875: 
 1876: user_get_muc_room_messages(User, RoomJID, PageSize, Before, Config) ->
 1877:     Vars = #{<<"room">> => jid:to_binary(RoomJID), <<"pageSize">> => PageSize,
 1878:                 <<"before">> => Before},
 1879:     execute_user_command(<<"muc">>, <<"getRoomMessages">>, User, Vars, Config).
 1880: 
 1881: send_message_to_muc_room(User, Room, Body, Resource, Config) ->
 1882:     Vars = #{room => jid:to_binary(Room), body => Body, resource => Resource},
 1883:     execute_user_command(<<"muc">>, <<"sendMessageToRoom">>, User, Vars, Config).
 1884: 
 1885: enter_muc_room(RoomJID, User, Nick) ->
 1886:     JID = jid:to_binary(jid:replace_resource(RoomJID, Nick)),
 1887:     Pres = escalus_stanza:to(escalus_stanza:presence(<<"available">>,
 1888:         [#xmlel{ name = <<"x">>, attrs=[{<<"xmlns">>, <<"http://jabber.org/protocol/muc">>}]}]),
 1889:         JID),
 1890:     escalus:send(User, Pres),
 1891:     escalus:wait_for_stanza(User).