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