1: -module(graphql_inbox_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]).
    7: -import(domain_helper, [host_type/0, domain/0]).
    8: -import(graphql_helper, [execute_user_command/5, execute_command/4, user_to_bin/1,
    9:                          get_ok_value/2, get_err_msg/1, get_err_code/1, get_not_loaded/1,
   10:                          get_unauthorized/1]).
   11: 
   12: -include_lib("common_test/include/ct.hrl").
   13: -include_lib("eunit/include/eunit.hrl").
   14: -include("inbox.hrl").
   15: 
   16: -define(assertErrMsg(Res, ContainsPart), assert_err_msg(ContainsPart, Res)).
   17: -define(assertErrCode(Res, Code), assert_err_code(Code, Res)).
   18: 
   19: suite() ->
   20:     require_rpc_nodes([mim]) ++ escalus:suite().
   21: 
   22: all() ->
   23:     inbox_helper:skip_or_run_inbox_tests(tests()).
   24: 
   25: tests() ->
   26:     [{group, user},
   27:      {group, admin_http},
   28:      {group, admin_cli},
   29:      {group, domain_admin_inbox}].
   30: 
   31: groups() ->
   32:     [{user, [], user_groups()},
   33:      {admin_http, [], admin_groups()},
   34:      {admin_cli, [], admin_groups()},
   35:      {user_inbox, [], user_inbox_tests()},
   36:      {user_inbox_not_configured, [], user_inbox_not_configured_tests()},
   37:      {admin_inbox, [], admin_inbox_tests()},
   38:      {admin_inbox_not_configured, [], admin_inbox_not_configured_tests()},
   39:      {domain_admin_inbox, [], domain_admin_inbox_tests()}].
   40: 
   41: user_groups() ->
   42:     [{group, user_inbox},
   43:      {group, user_inbox_not_configured}].
   44: 
   45: admin_groups() ->
   46:     [{group, admin_inbox},
   47:      {group, domain_admin_inbox}].
   48: 
   49: user_inbox_tests() ->
   50:     [user_flush_own_bin].
   51: 
   52: user_inbox_not_configured_tests() ->
   53:     [user_flush_own_bin_inbox_not_configured].
   54: 
   55: admin_inbox_tests() ->
   56:     [admin_flush_user_bin,
   57:      admin_try_flush_nonexistent_user_bin,
   58:      admin_try_flush_user_bin_nonexistent_domain,
   59:      admin_flush_domain_bin,
   60:      admin_flush_unprepped_domain_bin,
   61:      admin_try_flush_nonexistent_domain_bin,
   62:      admin_flush_global_bin,
   63:      admin_flush_global_bin_after_days,
   64:      admin_try_flush_nonexistent_host_type_bin].
   65: 
   66: domain_admin_inbox_tests() ->
   67:     [admin_flush_user_bin,
   68:      admin_try_flush_nonexistent_user_bin,
   69:      domain_admin_flush_user_bin_no_permission,
   70:      admin_flush_domain_bin,
   71:      domain_admin_try_flush_domain_bin_no_permission,
   72:      domain_admin_flush_global_bin_no_permission].
   73: 
   74: admin_inbox_not_configured_tests() ->
   75:     [admin_flush_user_bin_inbox_not_configured,
   76:      admin_flush_domain_bin_inbox_not_configured,
   77:      admin_flush_global_bin_inbox_not_configured].
   78: 
   79: init_per_suite(Config) ->
   80:     HostType = domain_helper:host_type(),
   81:     SecHostType = domain_helper:secondary_host_type(),
   82:     Config1 = dynamic_modules:save_modules([HostType, SecHostType], Config),
   83:     Config2 = ejabberd_node_utils:init(mim(), Config1),
   84:     escalus:init_per_suite(Config2).
   85: 
   86: end_per_suite(Config) ->
   87:     dynamic_modules:restore_modules(Config),
   88:     escalus:end_per_suite(Config).
   89: 
   90: init_per_group(user, Config) ->
   91:     graphql_helper:init_user(Config);
   92: init_per_group(admin_http, Config) ->
   93:     graphql_helper:init_admin_handler(Config);
   94: init_per_group(admin_cli, Config) ->
   95:     graphql_helper:init_admin_cli(Config);
   96: init_per_group(domain_admin_inbox, Config) ->
   97:     ensure_inbox_started(),
   98:     graphql_helper:init_domain_admin_handler(Config);
   99: init_per_group(Group, Config) when Group =:= user_inbox;
  100:                                    Group =:= admin_inbox ->
  101:     ensure_inbox_started(),
  102:     Config;
  103: init_per_group(Group, Config) when Group =:= user_inbox_not_configured;
  104:                                    Group =:= admin_inbox_not_configured ->
  105:     HostType = domain_helper:host_type(),
  106:     SecHostType = domain_helper:secondary_host_type(),
  107:     Modules = [{mod_inbox, stopped}],
  108:     ok = dynamic_modules:ensure_modules(HostType, Modules),
  109:     ok = dynamic_modules:ensure_modules(SecHostType, Modules),
  110:     Config.
  111: 
  112: ensure_inbox_started() ->
  113:     HostType = domain_helper:host_type(),
  114:     SecHostType = domain_helper:secondary_host_type(),
  115:     Modules = [{mod_inbox, inbox_helper:inbox_opts(async_pools)} | inbox_helper:muclight_modules()],
  116:     ok = dynamic_modules:ensure_modules(HostType, Modules),
  117:     ok = dynamic_modules:ensure_modules(SecHostType, Modules).
  118: 
  119: end_per_group(Group, _Config) when Group =:= user;
  120:                                    Group =:= admin_http;
  121:                                    Group =:= domain_admin_inbox;
  122:                                    Group =:= admin_cli ->
  123:     graphql_helper:clean();
  124: end_per_group(_Group, _Config) ->
  125:     escalus_fresh:clean().
  126: 
  127: init_per_testcase(CaseName, Config) ->
  128:     escalus:init_per_testcase(CaseName, Config).
  129: 
  130: end_per_testcase(CaseName, Config) ->
  131:     %% Clean users after each test case to keep inbox empty
  132:     escalus_fresh:clean(),
  133:     escalus:end_per_testcase(CaseName, Config).
  134: 
  135: %% Admin test cases
  136: 
  137: admin_flush_user_bin(Config) ->
  138:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}, {kate, 1}],
  139:                                     fun admin_flush_user_bin/4).
  140: 
  141: admin_flush_user_bin(Config, Alice, Bob, Kate) ->
  142:     RoomBinJID = create_room_and_make_users_leave(Alice, Bob, Kate),
  143:     Res = flush_user_bin(Bob, Config),
  144:     NumOfRows = get_ok_value(p(flushUserBin), Res),
  145:     ?assertEqual(1, NumOfRows),
  146:     inbox_helper:check_inbox(Bob, [], #{box => bin}),
  147:     check_aff_msg_in_inbox_bin(Kate, RoomBinJID).
  148: 
  149: admin_try_flush_nonexistent_user_bin(Config) ->
  150:     User = <<"nonexistent-user@", (domain_helper:domain())/binary>>,
  151:     Res2 = flush_user_bin(User, Config),
  152:     ?assertErrMsg(Res2, <<"does not exist">>),
  153:     ?assertErrCode(Res2, user_does_not_exist).
  154: 
  155: admin_try_flush_user_bin_nonexistent_domain(Config) ->
  156:     Res = flush_user_bin(<<"user@user.com">>, Config),
  157:     ?assertErrMsg(Res, <<"not found">>),
  158:     ?assertErrCode(Res, domain_not_found).
  159: 
  160: admin_flush_domain_bin(Config) ->
  161:     Config1 = [{domain, domain()} | Config],
  162:     escalus:fresh_story_with_config(Config1, [{alice, 1}, {alice_bis, 1}, {kate, 1}],
  163:                                     fun admin_flush_domain_bin/4).
  164: 
  165: admin_flush_unprepped_domain_bin(Config) ->
  166:     Config1 = [{domain, unprep(domain())} | Config],
  167:     escalus:fresh_story_with_config(Config1, [{alice, 1}, {alice_bis, 1}, {kate, 1}],
  168:                                     fun admin_flush_domain_bin/4).
  169: 
  170: admin_flush_domain_bin(Config, Alice, AliceBis, Kate) ->
  171:     RoomBinJID = create_room_and_make_users_leave(Alice, AliceBis, Kate),
  172:     Res = flush_domain_bin(?config(domain, Config), Config),
  173:     NumOfRows = get_ok_value(p(flushDomainBin), Res),
  174:     ?assertEqual(1, NumOfRows),
  175:     inbox_helper:check_inbox(Kate, [], #{box => bin}),
  176:     check_aff_msg_in_inbox_bin(AliceBis, RoomBinJID).
  177: 
  178: admin_try_flush_nonexistent_domain_bin(Config) ->
  179:     Res = flush_domain_bin(<<"unknown-domain">>, Config),
  180:     ?assertErrMsg(Res, <<"not found">>),
  181:     ?assertErrCode(Res, domain_not_found).
  182: 
  183: admin_flush_global_bin(Config) ->
  184:     escalus:fresh_story_with_config(Config, [{alice, 1}, {alice_bis, 1}, {kate, 1}],
  185:                                     fun admin_flush_global_bin/4).
  186: 
  187: admin_flush_global_bin(Config, Alice, AliceBis, Kate) ->
  188:     SecHostType = domain_helper:host_type(),
  189:     create_room_and_make_users_leave(Alice, AliceBis, Kate),
  190:     Res = flush_global_bin(SecHostType, null, Config),
  191:     NumOfRows = get_ok_value(p(flushGlobalBin), Res),
  192:     ?assertEqual(2, NumOfRows),
  193:     inbox_helper:check_inbox(AliceBis, [], #{box => bin}),
  194:     inbox_helper:check_inbox(Kate, [], #{box => bin}).
  195: 
  196: admin_flush_global_bin_after_days(Config) ->
  197:     escalus:fresh_story_with_config(Config, [{alice, 1}, {alice_bis, 1}, {kate, 1}],
  198:                                     fun admin_flush_global_bin_after_days/4).
  199: 
  200: admin_flush_global_bin_after_days(Config, Alice, AliceBis, Kate) ->
  201:     SecHostType = domain_helper:host_type(),
  202:     RoomBinJID = create_room_and_make_users_leave(Alice, AliceBis, Kate),
  203:     Res = flush_global_bin(SecHostType, 1, Config),
  204:     NumOfRows = get_ok_value(p(flushGlobalBin), Res),
  205:     ?assertEqual(0, NumOfRows),
  206:     check_aff_msg_in_inbox_bin(AliceBis, RoomBinJID),
  207:     check_aff_msg_in_inbox_bin(Kate, RoomBinJID).
  208: 
  209: admin_try_flush_nonexistent_host_type_bin(Config) ->
  210:     Res = flush_global_bin(<<"nonexistent host type">>, null, Config),
  211:     ?assertErrMsg(Res, <<"not found">>),
  212:     ?assertErrCode(Res, host_type_not_found).
  213: 
  214: % Admin inbox not configured test cases
  215: 
  216: admin_flush_user_bin_inbox_not_configured(Config) ->
  217:     escalus:fresh_story_with_config(Config, [{alice, 1}],
  218:                                     fun admin_flush_user_bin_inbox_not_configured/2).
  219: 
  220: admin_flush_user_bin_inbox_not_configured(Config, Alice) ->
  221:     get_not_loaded(flush_user_bin(Alice, Config)).
  222: 
  223: admin_flush_domain_bin_inbox_not_configured(Config) ->
  224:     get_not_loaded(flush_domain_bin(domain(), Config)),
  225:     get_not_loaded(flush_domain_bin(unprep(domain()), Config)).
  226: 
  227: admin_flush_global_bin_inbox_not_configured(Config) ->
  228:     get_not_loaded(flush_global_bin(host_type(), 10, Config)).
  229: 
  230: %% Domain admin test cases
  231: 
  232: domain_admin_flush_user_bin_no_permission(Config) ->
  233:     escalus:fresh_story_with_config(Config, [{alice_bis, 1}],
  234:                                     fun domain_admin_flush_user_bin_no_permission/2).
  235: 
  236: domain_admin_flush_user_bin_no_permission(Config, AliceBis) ->
  237:     Res = flush_user_bin(AliceBis, Config),
  238:     get_unauthorized(Res),
  239:     InvalidUser = <<"user@user.com">>,
  240:     Res2 = flush_user_bin(InvalidUser, Config),
  241:     get_unauthorized(Res2).
  242: 
  243: domain_admin_try_flush_domain_bin_no_permission(Config) ->
  244:     get_unauthorized(flush_domain_bin(<<"external-domain">>, Config)),
  245:     get_unauthorized(flush_domain_bin(domain_helper:secondary_domain(), Config)).
  246: 
  247: domain_admin_flush_global_bin_no_permission(Config) ->
  248:     escalus:fresh_story_with_config(Config, [{alice, 1}, {alice_bis, 1}, {kate, 1}],
  249:                                     fun domain_admin_flush_global_bin_no_permission/4).
  250: 
  251: domain_admin_flush_global_bin_no_permission(Config, Alice, AliceBis, Kate) ->
  252:     get_unauthorized(flush_global_bin(<<"nonexistent host type">>, null, Config)),
  253:     SecHostType = domain_helper:host_type(),
  254:     create_room_and_make_users_leave(Alice, AliceBis, Kate),
  255:     get_unauthorized(flush_global_bin(SecHostType, null, Config)).
  256: 
  257: %% User test cases
  258: 
  259: user_flush_own_bin(Config) ->
  260:     escalus:fresh_story_with_config(Config, [{alice, 1}, {bob, 1}, {kate, 1}],
  261:                                     fun user_flush_own_bin/4).
  262: 
  263: user_flush_own_bin(Config, Alice, Bob, Kate) ->
  264:     create_room_and_make_users_leave(Alice, Bob, Kate),
  265:     Res = user_flush_own_bin(Bob, Config),
  266:     NumOfRows = get_ok_value(p(flushBin), Res),
  267:     ?assertEqual(1, NumOfRows),
  268:     inbox_helper:check_inbox(Bob, [], #{box => bin}).
  269: 
  270: % User inbox not configured test cases
  271: 
  272: user_flush_own_bin_inbox_not_configured(Config) ->
  273:     escalus:fresh_story_with_config(Config, [{alice, 1}],
  274:                                     fun user_flush_own_bin_inbox_not_configured/2).
  275: 
  276: user_flush_own_bin_inbox_not_configured(Config, Alice) ->
  277:     get_not_loaded(user_flush_own_bin(Alice, Config)).
  278: 
  279: %% Helpers
  280: 
  281: create_room_and_make_users_leave(Alice, Bob, Kate) ->
  282:     RoomName = inbox_SUITE:create_room_and_make_users_leave(Alice, Bob, Kate),
  283:     muc_light_helper:room_bin_jid(RoomName).
  284: 
  285: check_aff_msg_in_inbox_bin(User, RoomBinJID) ->
  286:     UserShort = escalus_client:short_jid(User),
  287:     Convs = [#conv{unread = 1, from = RoomBinJID, to = UserShort, content = <<>>}],
  288:     inbox_helper:check_inbox(User, Convs, #{box => bin}).
  289: 
  290: assert_err_msg(Contains, Res) ->
  291:     ?assertNotEqual(nomatch, binary:match(get_err_msg(Res), Contains)).
  292: 
  293: assert_err_code(Code, Res) ->
  294:     ?assertEqual(atom_to_binary(Code), get_err_code(Res)).
  295: 
  296: p(Cmd) when is_atom(Cmd) ->
  297:     [data, inbox, Cmd];
  298: p(Path) when is_list(Path) ->
  299:     [data, inbox] ++ Path.
  300: 
  301: %% Commands
  302: 
  303: flush_user_bin(User, Config) ->
  304:     Vars = #{user => user_to_bin(User)},
  305:     graphql_helper:execute_command(<<"inbox">>, <<"flushUserBin">>, Vars, Config).
  306: 
  307: flush_domain_bin(Domain, Config) ->
  308:     Vars = #{domain => Domain},
  309:     graphql_helper:execute_command(<<"inbox">>, <<"flushDomainBin">>, Vars, Config).
  310: 
  311: flush_global_bin(HostType, Days, Config) ->
  312:     Vars = #{hostType => HostType, days => Days},
  313:     graphql_helper:execute_command(<<"inbox">>, <<"flushGlobalBin">>, Vars, Config).
  314: 
  315: user_flush_own_bin(User, Config) ->
  316:     graphql_helper:execute_user_command(<<"inbox">>, <<"flushBin">>, User, #{}, Config).