1: -module(graphql_stanza_SUITE).
    2: 
    3: -include_lib("eunit/include/eunit.hrl").
    4: -include_lib("exml/include/exml.hrl").
    5: 
    6: -compile([export_all, nowarn_export_all]).
    7: 
    8: -import(distributed_helper, [mim/0, require_rpc_nodes/1]).
    9: -import(graphql_helper, [execute_user_command/5, execute_command/4,
   10:                          execute_user_command_sse/5, execute_command_sse/4,
   11:                          get_ok_value/2, get_value/2,
   12:                          get_err_code/1, get_err_msg/1, get_coercion_err_msg/1,
   13:                          get_unauthorized/1, get_not_loaded/1]).
   14: 
   15: suite() ->
   16:     require_rpc_nodes([mim]) ++ escalus:suite().
   17: 
   18: all() ->
   19:     [{group, admin_stanza_http},
   20:      {group, admin_stanza_cli},
   21:      {group, domain_admin_stanza},
   22:      {group, user_stanza}].
   23: 
   24: groups() ->
   25:     [{admin_stanza_http, [], [{group, admin_mam},
   26:                               {group, admin_no_mam_http}]},
   27:      {admin_stanza_cli, [], [{group, admin_mam},
   28:                              {group, admin_no_mam_cli}]},
   29:      {domain_admin_stanza, [], [{group, admin_mam}, % same as for admin
   30:                                 {group, domain_admin_no_mam}]},
   31:      {user_stanza, [], [{group, user_mam},
   32:                         {group, user_no_mam}]},
   33:      {admin_mam, [parallel], admin_mam_cases()},
   34:      {admin_no_mam_http, [parallel], admin_stanza_cases(http) ++ admin_no_mam_cases()},
   35:      {admin_no_mam_cli, [], admin_stanza_cases(cli) ++ admin_no_mam_cases()},
   36:      {domain_admin_no_mam, [parallel], domain_admin_stanza_cases() ++ admin_no_mam_cases()},
   37:      {user_mam, [parallel], user_mam_cases()},
   38:      {user_no_mam, [parallel], user_stanza_cases() ++ user_no_mam_cases()}].
   39: 
   40: admin_stanza_cases(cli) ->
   41:     admin_stanza_cases();
   42: admin_stanza_cases(http) ->
   43:     admin_stanza_cases() ++ admin_sse_cases().
   44: 
   45: admin_stanza_cases() ->
   46:     [admin_send_message,
   47:      admin_send_message_to_unparsable_jid,
   48:      admin_send_message_headline,
   49:      admin_send_stanza,
   50:      admin_send_unparsable_stanza,
   51:      admin_send_stanza_from_unknown_user,
   52:      admin_send_stanza_from_unknown_domain].
   53: 
   54: admin_sse_cases() ->
   55:     [admin_subscribe_for_messages,
   56:      admin_subscribe_for_messages_to_unknown_user].
   57: 
   58: admin_mam_cases() ->
   59:     [admin_get_last_messages,
   60:      admin_get_last_messages_for_unknown_user,
   61:      admin_get_last_messages_with,
   62:      admin_get_last_messages_limit,
   63:      admin_get_last_messages_limit_null,
   64:      admin_get_last_messages_limit_enforced,
   65:      admin_get_last_messages_before].
   66: 
   67: admin_no_mam_cases() ->
   68:     [admin_get_last_messages_no_mam].
   69: 
   70: domain_admin_stanza_cases() ->
   71:     [admin_send_message,
   72:      admin_send_message_to_unparsable_jid,
   73:      admin_send_message_headline,
   74:      domain_admin_send_message_no_permission,
   75:      domain_admin_send_stanza,
   76:      admin_send_unparsable_stanza,
   77:      domain_admin_send_stanza_from_unknown_user,
   78:      domain_admin_send_stanza_from_unknown_domain,
   79:      domain_admin_get_last_messages_no_permission].
   80: 
   81: user_stanza_cases() ->
   82:     [user_send_message,
   83:      user_subscribe_for_messages,
   84:      user_send_message_without_from,
   85:      user_send_message_with_spoofed_from,
   86:      user_send_message_headline,
   87:      user_send_message_headline_with_spoofed_from,
   88:      user_send_stanza,
   89:      user_send_stanza_without_from_with_id,
   90:      user_send_stanza_with_spoofed_from].
   91: 
   92: user_mam_cases() ->
   93:     [user_get_last_messages].
   94: 
   95: user_no_mam_cases() ->
   96:     [user_get_last_messages_no_mam].
   97: 
   98: init_per_suite(Config) ->
   99:     Config1 = ejabberd_node_utils:init(mim(), Config),
  100:     Config2 = escalus:init_per_suite(Config1),
  101:     dynamic_modules:save_modules(domain_helper:host_type(), Config2).
  102: 
  103: end_per_suite(Config) ->
  104:     dynamic_modules:restore_modules(Config),
  105:     escalus:end_per_suite(Config).
  106: 
  107: init_per_group(admin_stanza_http, Config) ->
  108:     graphql_helper:init_admin_handler(Config);
  109: init_per_group(admin_stanza_cli, Config) ->
  110:     graphql_helper:init_admin_cli(Config);
  111: init_per_group(domain_admin_stanza, Config) ->
  112:     graphql_helper:init_domain_admin_handler(Config);
  113: init_per_group(user_stanza, Config) ->
  114:     graphql_helper:init_user(Config);
  115: init_per_group(GN, Config) when GN =:= admin_mam;
  116:                                 GN =:= domain_admin_mam;
  117:                                 GN =:= user_mam ->
  118:     init_mam(Config);
  119: init_per_group(GN, Config) when GN =:= admin_no_mam_http;
  120:                                 GN =:= admin_no_mam_cli;
  121:                                 GN =:= domain_admin_no_mam;
  122:                                 GN =:= user_no_mam ->
  123:     Mods = [{mod_mam, stopped}],
  124:     dynamic_modules:ensure_modules(domain_helper:host_type(), Mods),
  125:     Config.
  126: 
  127: end_per_group(GN, _Config) when GN =:= admin_stanza_http;
  128:                                 GN =:= admin_stanza_cli;
  129:                                 GN =:= domain_admin_stanza;
  130:                                 GN =:= user_stanza ->
  131:     graphql_helper:clean();
  132: end_per_group(_GN, _Config) ->
  133:     escalus_fresh:clean().
  134: 
  135: init_per_testcase(CaseName, Config) ->
  136:     escalus:init_per_testcase(CaseName, Config).
  137: 
  138: end_per_testcase(CaseName, Config) ->
  139:     escalus:end_per_testcase(CaseName, Config).
  140: 
  141: init_mam(Config) when is_list(Config) ->
  142:     case mam_helper:backend() of
  143:         disabled ->
  144:             {skip, no_mam};
  145:         Backend ->
  146:             MAMOpts = mam_helper:config_opts(#{backend => Backend, pm => #{}}),
  147:             Mods = [{mod_mam, MAMOpts}],
  148:             dynamic_modules:ensure_modules(domain_helper:host_type(), Mods),
  149:             Config
  150:     end;
  151: init_mam(Other) ->
  152:     Other.
  153: 
  154: %% Test Cases
  155: 
  156: admin_send_message(Config) ->
  157:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  158:                                     fun admin_send_message_story/3).
  159: 
  160: admin_send_message_story(Config, Alice, Bob) ->
  161:     From = escalus_client:full_jid(Alice),
  162:     To = escalus_client:short_jid(Bob),
  163:     Res = send_message(From, To, <<"Hi!">>, Config),
  164:     #{<<"id">> := StanzaId} = get_ok_value([data, stanza, sendMessage], Res),
  165:     assert_not_empty(StanzaId),
  166:     escalus:assert(is_message, escalus:wait_for_stanza(Bob)).
  167: 
  168: admin_subscribe_for_messages_to_unknown_user(Config) ->
  169:     Domain = domain_helper:domain(),
  170:     Res = subscribe_for_messages(<<"baduser@", Domain/binary>>, Config),
  171:     ?assertEqual(<<"unknown_user">>, get_err_code(Res)),
  172:     ?assertEqual(<<"User does not exist">>, get_err_msg(Res)).
  173: 
  174: admin_subscribe_for_messages(Config) ->
  175:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  176:                                     fun admin_subscribe_for_messages_story/3).
  177: 
  178: admin_subscribe_for_messages_story(Config, Alice, Bob) ->
  179:     From = escalus_client:full_jid(Alice),
  180:     To = escalus_client:short_jid(Bob),
  181:     {200, Stream} = subscribe_for_messages(To, Config),
  182:     %% Presence should be skipped
  183:     escalus:send(Alice, escalus_stanza:presence_direct(To, <<"available">>)),
  184:     %% Message should be delivered
  185:     escalus:send(Alice, escalus_stanza:chat(From, To, <<"Hi!">>)),
  186:     Event = sse_helper:wait_for_event(Stream),
  187:     #{<<"stanza">> := StanzaBin, <<"sender">> := From} =
  188:         graphql_helper:get_value([data, stanza, subscribeForMessages], Event),
  189:     {ok, Stanza} = exml:parse(StanzaBin),
  190:     escalus:assert(is_message, Stanza),
  191:     sse_helper:stop_sse(Stream).
  192: 
  193: user_send_message(Config) ->
  194:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  195:                                     fun user_send_message_story/3).
  196: 
  197: user_send_message_story(Config, Alice, Bob) ->
  198:     From = escalus_client:full_jid(Alice),
  199:     To = escalus_client:short_jid(Bob),
  200:     Res = user_send_message(Alice, From, To, <<"Hi!">>, Config),
  201:     #{<<"id">> := StanzaId} = get_ok_value([data, stanza, sendMessage], Res),
  202:     assert_not_empty(StanzaId),
  203:     escalus:assert(is_message, escalus:wait_for_stanza(Bob)).
  204: 
  205: user_subscribe_for_messages(Config) ->
  206:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  207:                                     fun user_subscribe_for_messages_story/3).
  208: 
  209: user_subscribe_for_messages_story(Config, Alice, Bob) ->
  210:     From = escalus_client:full_jid(Alice),
  211:     To = escalus_client:short_jid(Bob),
  212:     {200, Stream} = user_subscribe_for_messages(Bob, Config),
  213:     escalus:send(Alice, escalus_stanza:chat(From, To, <<"Hi!">>)),
  214:     Event = sse_helper:wait_for_event(Stream),
  215:     #{<<"stanza">> := StanzaBin, <<"sender">> := From} =
  216:         graphql_helper:get_value([data, stanza, subscribeForMessages], Event),
  217:     {ok, Stanza} = exml:parse(StanzaBin),
  218:     escalus:assert(is_message, Stanza),
  219:     sse_helper:stop_sse(Stream).
  220: 
  221: user_send_message_without_from(Config) ->
  222:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  223:                                     fun user_send_message_without_from_story/3).
  224: 
  225: user_send_message_without_from_story(Config, Alice, Bob) ->
  226:     To = escalus_client:short_jid(Bob),
  227:     Res = user_send_message(Alice, null, To, <<"Hi!">>, Config),
  228:     #{<<"id">> := StanzaId} = get_ok_value([data, stanza, sendMessage], Res),
  229:     assert_not_empty(StanzaId),
  230:     escalus:assert(is_message, escalus:wait_for_stanza(Bob)).
  231: 
  232: user_send_message_with_spoofed_from(Config) ->
  233:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  234:                                     fun user_send_message_with_spoofed_from_story/3).
  235: 
  236: user_send_message_with_spoofed_from_story(Config, Alice, Bob) ->
  237:     To = From = escalus_client:short_jid(Bob),
  238:     Res = user_send_message(Alice, From, To, <<"Hi!">>, Config),
  239:     spoofed_error(sendMessage, Res).
  240: 
  241: admin_send_message_to_unparsable_jid(Config) ->
  242:     escalus:fresh_story_with_config(Config, [{alice, 1}],
  243:                                     fun admin_send_message_to_unparsable_jid_story/2).
  244: 
  245: admin_send_message_to_unparsable_jid_story(Config, Alice) ->
  246:     From = escalus_client:full_jid(Alice),
  247:     To = <<"test@">>,
  248:     Res = send_message(From, To, <<"Hi!">>, Config),
  249:     ?assertEqual(<<"Input coercion failed for type JID with value "
  250:                    "<<\"test@\">>. The reason it failed is: failed_to_parse_jid">>,
  251:                  get_coercion_err_msg(Res)).
  252: 
  253: admin_send_message_headline(Config) ->
  254:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  255:                                     fun admin_send_message_headline_story/3).
  256: 
  257: admin_send_message_headline_story(Config, Alice, Bob) ->
  258:     From = escalus_client:full_jid(Alice),
  259:     To = escalus_client:short_jid(Bob),
  260:     Res = send_message_headline(From, To, <<"Welcome">>, <<"Hi!">>, Config),
  261:     #{<<"id">> := StanzaId} = get_ok_value([data, stanza, sendMessageHeadLine], Res),
  262:     assert_not_empty(StanzaId),
  263:     escalus:assert(is_message, escalus:wait_for_stanza(Bob)),
  264:     Res2 = send_message_headline(From, To, null, null, Config),
  265:     #{<<"id">> := StanzaId2} = get_ok_value([data, stanza, sendMessageHeadLine], Res2),
  266:     assert_not_empty(StanzaId2),
  267:     escalus:assert(is_message, escalus:wait_for_stanza(Bob)).
  268: 
  269: user_send_message_headline(Config) ->
  270:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  271:                                     fun user_send_message_headline_story/3).
  272: 
  273: user_send_message_headline_story(Config, Alice, Bob) ->
  274:     From = escalus_client:full_jid(Alice),
  275:     To = escalus_client:short_jid(Bob),
  276:     Res = user_send_message_headline(Alice, From, To, <<"Welcome">>, <<"Hi!">>, Config),
  277:     #{<<"id">> := StanzaId} = get_ok_value([data, stanza, sendMessageHeadLine], Res),
  278:     assert_not_empty(StanzaId),
  279:     escalus:assert(is_message, escalus:wait_for_stanza(Bob)).
  280: 
  281: user_send_message_headline_with_spoofed_from(Config) ->
  282:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  283:                                     fun user_send_message_headline_with_spoofed_from_story/3).
  284: 
  285: user_send_message_headline_with_spoofed_from_story(Config, Alice, Bob) ->
  286:     To = From = escalus_client:short_jid(Bob),
  287:     Res = user_send_message_headline(Alice, From, To, <<"Welcome">>, <<"Hi!">>, Config),
  288:     spoofed_error(sendMessageHeadLine, Res).
  289: 
  290: domain_admin_send_message_no_permission(Config) ->
  291:     escalus:fresh_story_with_config(Config, [{alice_bis, 1}, {bob, 1}],
  292:                                     fun domain_admin_send_message_no_permission_story/3).
  293: 
  294: domain_admin_send_message_no_permission_story(Config, AliceBis, Bob) ->
  295:     From = escalus_client:full_jid(AliceBis),
  296:     To = escalus_client:short_jid(Bob),
  297:     Res = send_message(From, To, <<"Hi!">>, Config),
  298:     get_unauthorized(Res).
  299: 
  300: domain_admin_send_stanza(Config) ->
  301:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  302:                                     fun domain_admin_send_stanza_story/3).
  303: 
  304: domain_admin_send_stanza_story(Config, Alice, Bob) ->
  305:     Body = <<"Hi!">>,
  306:     Stanza = escalus_stanza:from(escalus_stanza:chat_to_short_jid(Bob, Body), Alice),
  307:     Res = send_stanza(exml:to_binary(Stanza), Config),
  308:     get_unauthorized(Res).
  309: 
  310: domain_admin_send_stanza_from_unknown_user(Config) ->
  311:     escalus:fresh_story_with_config(Config, [{bob, 1}],
  312:                                     fun domain_admin_send_stanza_from_unknown_user_story/2).
  313: 
  314: domain_admin_send_stanza_from_unknown_user_story(Config, Bob) ->
  315:     Body = <<"Hi!">>,
  316:     Server = escalus_client:server(Bob),
  317:     From = <<"YeeeAH@", Server/binary>>,
  318:     Stanza = escalus_stanza:from(escalus_stanza:chat_to_short_jid(Bob, Body), From),
  319:     Res = send_stanza(exml:to_binary(Stanza), Config),
  320:     get_unauthorized(Res).
  321: 
  322: domain_admin_send_stanza_from_unknown_domain(Config) ->
  323:     escalus:fresh_story_with_config(Config, [{bob, 1}],
  324:                                     fun domain_admin_send_stanza_from_unknown_domain_story/2).
  325: 
  326: domain_admin_send_stanza_from_unknown_domain_story(Config, Bob) ->
  327:     Body = <<"Hi!">>,
  328:     From = <<"YeeeAH@oopsie">>,
  329:     Stanza = escalus_stanza:from(escalus_stanza:chat_to_short_jid(Bob, Body), From),
  330:     Res = send_stanza(exml:to_binary(Stanza), Config),
  331:     get_unauthorized(Res).
  332: 
  333: domain_admin_get_last_messages_no_permission(Config) ->
  334:     escalus:fresh_story_with_config(Config, [{alice_bis, 1}],
  335:                                     fun domain_admin_get_last_messages_story_no_permission/2).
  336: 
  337: domain_admin_get_last_messages_story_no_permission(Config, AliceBis) ->
  338:     Res = get_last_messages(escalus_client:full_jid(AliceBis), null, null, Config),
  339:     get_unauthorized(Res).
  340: 
  341: admin_send_stanza(Config) ->
  342:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  343:                                     fun admin_send_stanza_story/3).
  344: 
  345: admin_send_stanza_story(Config, Alice, Bob) ->
  346:     Body = <<"Hi!">>,
  347:     Stanza = escalus_stanza:from(escalus_stanza:chat_to_short_jid(Bob, Body), Alice),
  348:     Res = send_stanza(exml:to_binary(Stanza), Config),
  349:     #{<<"id">> := StanzaId} = get_ok_value([data, stanza, sendStanza], Res),
  350:     assert_not_empty(StanzaId),
  351:     StanzaIn = escalus:wait_for_stanza(Bob),
  352:     escalus:assert(is_message, StanzaIn),
  353:     ?assertEqual(StanzaId, exml_query:attr(StanzaIn, <<"id">>)).
  354: 
  355: user_send_stanza(Config) ->
  356:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  357:                                     fun user_send_stanza_story/3).
  358: 
  359: user_send_stanza_story(Config, Alice, Bob) ->
  360:     Body = <<"Hi!">>,
  361:     Stanza = escalus_stanza:from(escalus_stanza:chat_to_short_jid(Bob, Body), Alice),
  362:     Res = user_send_stanza(Alice, exml:to_binary(Stanza), Config),
  363:     #{<<"id">> := StanzaId} = get_ok_value([data, stanza, sendStanza], Res),
  364:     assert_not_empty(StanzaId),
  365:     StanzaIn = escalus:wait_for_stanza(Bob),
  366:     escalus:assert(is_message, StanzaIn),
  367:     ?assertEqual(StanzaId, exml_query:attr(StanzaIn, <<"id">>)).
  368: 
  369: user_send_stanza_without_from_with_id(Config) ->
  370:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  371:                                     fun user_send_stanza_without_from_with_id_story/3).
  372: 
  373: user_send_stanza_without_from_with_id_story(Config, Alice, Bob) ->
  374:     Body = <<"Hi!">>,
  375:     StanzaId = base16:encode(crypto:strong_rand_bytes(8)),
  376:     Stanza = escalus_stanza:set_id(escalus_stanza:chat_to_short_jid(Bob, Body), StanzaId),
  377:     Res = user_send_stanza(Alice, exml:to_binary(Stanza), Config),
  378:     ?assertEqual(#{<<"id">> => StanzaId}, get_ok_value([data, stanza, sendStanza], Res)),
  379:     StanzaIn = escalus:wait_for_stanza(Bob),
  380:     escalus:assert(is_message, StanzaIn),
  381:     ?assertEqual(StanzaId, exml_query:attr(StanzaIn, <<"id">>)).
  382: 
  383: user_send_stanza_with_spoofed_from(Config) ->
  384:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  385:                                     fun user_send_stanza_with_spoofed_from_story/3).
  386: 
  387: user_send_stanza_with_spoofed_from_story(Config, Alice, Bob) ->
  388:     Body = <<"Hi!">>,
  389:     Stanza = escalus_stanza:from(escalus_stanza:chat_to_short_jid(Bob, Body), Bob),
  390:     Res = user_send_stanza(Alice, exml:to_binary(Stanza), Config),
  391:     spoofed_error(sendStanza, Res).
  392: 
  393: admin_send_unparsable_stanza(Config) ->
  394:     Res = send_stanza(<<"<test">>, Config),
  395:     ?assertEqual(<<"Input coercion failed for type XmlElement with value <<\"<test\">>. "
  396:                    "The reason it failed is: \"expected >\"">>,
  397:                  get_coercion_err_msg(Res)).
  398: 
  399: admin_send_stanza_from_unknown_user(Config) ->
  400:     escalus:fresh_story_with_config(Config, [{bob, 1}],
  401:                                     fun admin_send_stanza_from_unknown_user_story/2).
  402: 
  403: admin_send_stanza_from_unknown_user_story(Config, Bob) ->
  404:     Body = <<"Hi!">>,
  405:     Server = escalus_client:server(Bob),
  406:     From = <<"YeeeAH@", Server/binary>>,
  407:     Stanza = escalus_stanza:from(escalus_stanza:chat_to_short_jid(Bob, Body), From),
  408:     Res = send_stanza(exml:to_binary(Stanza), Config),
  409:     ?assertEqual(<<"unknown_user">>, get_err_code(Res)),
  410:     ?assertEqual(<<"User does not exist">>, get_err_msg(Res)).
  411: 
  412: admin_send_stanza_from_unknown_domain(Config) ->
  413:     escalus:fresh_story_with_config(Config, [{bob, 1}],
  414:                                     fun admin_send_stanza_from_unknown_domain_story/2).
  415: 
  416: admin_send_stanza_from_unknown_domain_story(Config, Bob) ->
  417:     Body = <<"Hi!">>,
  418:     From = <<"YeeeAH@oopsie">>,
  419:     Stanza = escalus_stanza:from(escalus_stanza:chat_to_short_jid(Bob, Body), From),
  420:     Res = send_stanza(exml:to_binary(Stanza), Config),
  421:     ?assertEqual(<<"unknown_user">>, get_err_code(Res)),
  422:     ?assertEqual(<<"User's domain does not exist">>, get_err_msg(Res)).
  423: 
  424: admin_get_last_messages(Config) ->
  425:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  426:                                     fun admin_get_last_messages_story/3).
  427: 
  428: admin_get_last_messages_story(Config, Alice, Bob) ->
  429:     admin_send_message_story(Config, Alice, Bob),
  430:     mam_helper:wait_for_archive_size(Alice, 1),
  431:     mam_helper:wait_for_archive_size(Bob, 1),
  432:     Res1 = get_last_messages(escalus_client:full_jid(Alice), null, null, Config),
  433:     #{<<"stanzas">> := [M1], <<"limit">> := 50} =
  434:         get_ok_value([data, stanza, getLastMessages], Res1),
  435:     check_stanza_map(M1, Alice),
  436:     Res2 = get_last_messages(escalus_client:full_jid(Bob), null, null, Config),
  437:     #{<<"stanzas">> := [M2], <<"limit">> := 50} =
  438:         get_ok_value([data, stanza, getLastMessages], Res2),
  439:     check_stanza_map(M2, Alice).
  440: 
  441: admin_get_last_messages_no_mam(Config) ->
  442:     FreshConfig = escalus_fresh:create_users(Config, [{alice, 1}]),
  443:     AliceJid = escalus_users:get_jid(FreshConfig, alice),
  444:     Res = get_last_messages(AliceJid, null, null, Config),
  445:     get_not_loaded(Res).
  446: 
  447: user_get_last_messages(Config) ->
  448:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  449:                                     fun user_get_last_messages_story/3).
  450: 
  451: user_get_last_messages_story(Config, Alice, Bob) ->
  452:     user_send_message_story(Config, Alice, Bob),
  453:     mam_helper:wait_for_archive_size(Alice, 1),
  454:     mam_helper:wait_for_archive_size(Bob, 1),
  455:     Res1 = user_get_last_messages(Alice, null, null, Config),
  456:     #{<<"stanzas">> := [M1], <<"limit">> := 50} =
  457:         get_ok_value([data, stanza, getLastMessages], Res1),
  458:     check_stanza_map(M1, Alice),
  459:     Res2 = user_get_last_messages(Bob, null, null, Config),
  460:     #{<<"stanzas">> := [M2], <<"limit">> := 50} =
  461:         get_ok_value([data, stanza, getLastMessages], Res2),
  462:     check_stanza_map(M2, Alice).
  463: 
  464: user_get_last_messages_no_mam(Config) ->
  465:     escalus:fresh_story_with_config(Config, [{alice, 1}],
  466:                                     fun user_get_last_messages_no_mam_story/2).
  467: 
  468: user_get_last_messages_no_mam_story(Config, Alice) ->
  469:     Res = user_get_last_messages(Alice, null, null, Config),
  470:     get_not_loaded(Res).
  471: 
  472: admin_get_last_messages_for_unknown_user(Config) ->
  473:     Domain = domain_helper:domain(),
  474:     Jid = <<"maybemaybebutnot@", Domain/binary>>,
  475:     Res = get_last_messages(Jid, null, null, Config),
  476:     ?assertEqual(<<"unknown_user">>, get_err_code(Res)),
  477:     ?assertEqual(<<"User does not exist">>, get_err_msg(Res)).
  478: 
  479: admin_get_last_messages_with(Config) ->
  480:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}, {kate, 1}],
  481:                                     fun admin_get_last_messages_with_story/4).
  482: 
  483: admin_get_last_messages_with_story(Config, Alice, Bob, Kate) ->
  484:     admin_send_message_story(Config, Alice, Bob),
  485:     mam_helper:wait_for_archive_size(Alice, 1),
  486:     admin_send_message_story(Config, Kate, Alice),
  487:     mam_helper:wait_for_archive_size(Alice, 2),
  488:     Caller = escalus_client:full_jid(Alice),
  489:     With = escalus_client:short_jid(Bob),
  490:     Res = get_last_messages(Caller, With, null, Config),
  491:     #{<<"stanzas">> := [M1], <<"limit">> := 50} =
  492:         get_ok_value([data, stanza, getLastMessages], Res),
  493:     check_stanza_map(M1, Alice).
  494: 
  495: admin_get_last_messages_limit(Config) ->
  496:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  497:                                     fun admin_get_last_messages_limit_story/3).
  498: 
  499: admin_get_last_messages_limit_story(Config, Alice, Bob) ->
  500:     admin_send_message_story(Config, Alice, Bob),
  501:     mam_helper:wait_for_archive_size(Alice, 1),
  502:     admin_send_message_story(Config, Bob, Alice),
  503:     mam_helper:wait_for_archive_size(Alice, 2),
  504:     Caller = escalus_client:full_jid(Alice),
  505:     Res = get_last_messages(Caller, null, 1, null, Config),
  506:     #{<<"stanzas">> := [M1], <<"limit">> := 1} =
  507:         get_ok_value([data, stanza, getLastMessages], Res),
  508:     check_stanza_map(M1, Bob).
  509: 
  510: admin_get_last_messages_limit_null(Config) ->
  511:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  512:                                     fun admin_get_last_messages_limit_null_story/3).
  513: 
  514: admin_get_last_messages_limit_null_story(Config, Alice, Bob) ->
  515:     admin_send_message_story(Config, Alice, Bob),
  516:     mam_helper:wait_for_archive_size(Alice, 1),
  517:     Caller = escalus_client:full_jid(Alice),
  518:     Res = get_last_messages(Caller, null, null, null, Config),
  519:     #{<<"stanzas">> := [M1], <<"limit">> := 50} =
  520:         get_ok_value([data, stanza, getLastMessages], Res),
  521:     check_stanza_map(M1, Alice).
  522: 
  523: admin_get_last_messages_limit_enforced(Config) ->
  524:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  525:                                     fun admin_get_last_messages_limit_enforced_story/3).
  526: 
  527: admin_get_last_messages_limit_enforced_story(Config, Alice, Bob) ->
  528:     admin_send_message_story(Config, Alice, Bob),
  529:     mam_helper:wait_for_archive_size(Alice, 1),
  530:     Caller = escalus_client:full_jid(Alice),
  531:     Res = get_last_messages(Caller, null, 1000, null, Config),
  532:     %% The actual limit is returned
  533:     #{<<"stanzas">> := [M1], <<"limit">> := 50} =
  534:         get_ok_value([data, stanza, getLastMessages], Res),
  535:     check_stanza_map(M1, Alice).
  536: 
  537: admin_get_last_messages_before(Config) ->
  538:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}],
  539:                                     fun admin_get_last_messages_before_story/3).
  540: 
  541: admin_get_last_messages_before_story(Config, Alice, Bob) ->
  542:     admin_send_message_story(Config, Alice, Bob),
  543:     mam_helper:wait_for_archive_size(Alice, 1),
  544:     admin_send_message_story(Config, Bob, Alice),
  545:     mam_helper:wait_for_archive_size(Alice, 2),
  546:     admin_send_message_story(Config, Bob, Alice),
  547:     mam_helper:wait_for_archive_size(Alice, 3),
  548:     Caller = escalus_client:full_jid(Alice),
  549:     Res1 = get_last_messages(Caller, null, null, Config),
  550:     #{<<"stanzas">> := [M1, M2, _M3], <<"limit">> := 50} =
  551:         get_ok_value([data, stanza, getLastMessages], Res1),
  552:     Before = maps:get(<<"timestamp">>, M2),
  553:     Res2 = get_last_messages(Caller, null, Before, Config),
  554:     #{<<"stanzas">> := [M1, M2], <<"limit">> := 50} =
  555:         get_ok_value([data, stanza, getLastMessages], Res2).
  556: 
  557: %% Commands
  558: 
  559: send_message(From, To, Body, Config) ->
  560:     Vars = #{from => From, to => To, body => Body},
  561:     execute_command(<<"stanza">>, <<"sendMessage">>, Vars, Config).
  562: 
  563: user_send_message(User, From, To, Body, Config) ->
  564:     Vars = #{from => From, to => To, body => Body},
  565:     execute_user_command(<<"stanza">>, <<"sendMessage">>, User, Vars, Config).
  566: 
  567: send_message_headline(From, To, Subject, Body, Config) ->
  568:     Vars = #{from => From, to => To, subject => Subject, body => Body},
  569:     execute_command(<<"stanza">>, <<"sendMessageHeadLine">>, Vars, Config).
  570: 
  571: user_send_message_headline(User, From, To, Subject, Body, Config) ->
  572:     Vars = #{from => From, to => To, subject => Subject, body => Body},
  573:     execute_user_command(<<"stanza">>, <<"sendMessageHeadLine">>, User, Vars, Config).
  574: 
  575: send_stanza(Stanza, Config) ->
  576:     Vars = #{stanza => Stanza},
  577:     execute_command(<<"stanza">>, <<"sendStanza">>, Vars, Config).
  578: 
  579: user_send_stanza(User, Stanza, Config) ->
  580:     Vars = #{stanza => Stanza},
  581:     execute_user_command(<<"stanza">>, <<"sendStanza">>, User, Vars, Config).
  582: 
  583: subscribe_for_messages(Caller, Config) ->
  584:     Vars = #{caller => Caller},
  585:     execute_command_sse(<<"stanza">>, <<"subscribeForMessages">>, Vars, Config).
  586: 
  587: user_subscribe_for_messages(User, Config) ->
  588:     execute_user_command_sse(<<"stanza">>, <<"subscribeForMessages">>, User, #{}, Config).
  589: 
  590: get_last_messages(Caller, With, Before, Config) ->
  591:     Vars = #{caller => Caller, with => With, before => Before},
  592:     execute_command(<<"stanza">>, <<"getLastMessages">>, Vars, Config).
  593: 
  594: get_last_messages(Caller, With, Limit, Before, Config) ->
  595:     Vars = #{caller => Caller, with => With, limit => Limit, before => Before},
  596:     execute_command(<<"stanza">>, <<"getLastMessages">>, Vars, Config).
  597: 
  598: user_get_last_messages(User, With, Before, Config) ->
  599:     Vars = #{with => With, before => Before},
  600:     execute_user_command(<<"stanza">>, <<"getLastMessages">>, User, Vars, Config).
  601: 
  602: %% Helpers
  603: 
  604: assert_not_empty(Bin) when byte_size(Bin) > 0 -> ok.
  605: 
  606: ok_result(What1, What2, {{<<"200">>, <<"OK">>}, #{<<"data">> := Data}}) ->
  607:     maps:get(What2, maps:get(What1, Data)).
  608: 
  609: check_stanza_map(#{<<"sender">> := SenderJID,
  610:                    <<"stanza">> := XML,
  611:                    <<"stanza_id">> := StanzaID,
  612:                    <<"timestamp">> := TS}, SenderClient) ->
  613:     ?assertEqual(escalus_utils:jid_to_lower(escalus_client:full_jid(SenderClient)),
  614:                  escalus_utils:jid_to_lower(SenderJID)),
  615:      true = byte_size(StanzaID) > 6,
  616:      true = is_integer(calendar:rfc3339_to_system_time(binary_to_list(TS))),
  617:      {ok, #xmlel{name = <<"message">>}} = exml:parse(XML).
  618: 
  619: spoofed_error(Call, Response) ->
  620:     null = graphql_helper:get_err_value([data, stanza, Call], Response),
  621:     ?assertEqual(<<"Sender's JID is different from the user's JID">>, get_err_msg(Response)),
  622:     ?assertEqual(<<"invalid_sender">>, get_err_code(Response)).