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