1: -module(graphql_SUITE).
    2: 
    3: -include_lib("common_test/include/ct.hrl").
    4: -include_lib("eunit/include/eunit.hrl").
    5: -include_lib("exml/include/exml.hrl").
    6: 
    7: -compile([export_all, nowarn_export_all]).
    8: 
    9: -import(distributed_helper, [mim/0, require_rpc_nodes/1, rpc/4]).
   10: -import(graphql_helper, [execute/3, execute_auth/2, execute_domain_auth/2, execute_user/3]).
   11: 
   12: -define(assertAdminAuth(Domain, Type, Auth, Data),
   13:         assert_auth(#{<<"domain">> => Domain,
   14:                       <<"authStatus">> => atom_to_binary(Auth),
   15:                       <<"authType">> => maybe_atom_to_bin(Type)}, Data)).
   16: -define(assertUserAuth(Username, Auth, Data),
   17:         assert_auth(#{<<"username">> => Username,
   18:                       <<"authStatus">> => atom_to_binary(Auth)}, Data)).
   19: 
   20: suite() ->
   21:     require_rpc_nodes([mim]) ++ escalus:suite().
   22: 
   23: all() ->
   24:     [{group, cowboy_handler},
   25:      {group, admin_handler},
   26:      {group, domain_admin_handler},
   27:      {group, user_handler}].
   28: 
   29: groups() ->
   30:     [{cowboy_handler, [parallel], cowboy_handler()},
   31:      {user_handler, [parallel], user_handler()},
   32:      {domain_admin_handler, [parallel], domain_admin_handler()},
   33:      {admin_handler, [parallel], admin_handler()}].
   34: 
   35: cowboy_handler() ->
   36:     [can_connect_to_admin,
   37:      can_connect_to_domain_admin,
   38:      can_connect_to_user].
   39: 
   40: user_handler() ->
   41:     [user_checks_auth,
   42:      auth_user_checks_auth | common_tests()].
   43: admin_handler() ->
   44:     [admin_checks_auth,
   45:      auth_admin_checks_auth | common_tests()].
   46: domain_admin_handler() ->
   47:     [domain_admin_checks_auth,
   48:      auth_domain_admin_checks_auth | common_tests()].
   49: 
   50: common_tests() ->
   51:     [can_load_graphiql].
   52: 
   53: init_per_suite(Config) ->
   54:     Config1 = escalus:init_per_suite(Config),
   55:     dynamic_modules:save_modules(domain_helper:host_type(), Config1).
   56: 
   57: end_per_suite(Config) ->
   58:     dynamic_modules:restore_modules(Config),
   59:     escalus_fresh:clean(),
   60:     escalus:end_per_suite(Config).
   61: 
   62: init_per_group(admin_handler, Config) ->
   63:     graphql_helper:init_admin_handler(Config);
   64: init_per_group(domain_admin_handler, Config) ->
   65:     case mongoose_helper:is_rdbms_enabled(domain_helper:host_type()) of
   66:         true ->
   67:             graphql_helper:init_domain_admin_handler(Config);
   68:         false ->
   69:             {skip, require_rdbms}
   70:     end;
   71: init_per_group(user_handler, Config) ->
   72:     Config1 = escalus:create_users(Config, escalus:get_users([alice])),
   73:     [{schema_endpoint, user} | Config1];
   74: init_per_group(cowboy_handler, Config) ->
   75:     Config.
   76: 
   77: end_per_group(user_handler, Config) ->
   78:     escalus:delete_users(Config, escalus:get_users([alice]));
   79: end_per_group(domain_admin_handler, Config) ->
   80:     graphql_helper:end_domain_admin_handler(Config);
   81: end_per_group(_, _Config) ->
   82:     ok.
   83: 
   84: init_per_testcase(CaseName, Config) ->
   85:     escalus:init_per_testcase(CaseName, Config).
   86: 
   87: end_per_testcase(CaseName, Config) ->
   88:     escalus:end_per_testcase(CaseName, Config).
   89: 
   90: can_connect_to_admin(_Config) ->
   91:     ?assertMatch({{<<"400">>, <<"Bad Request">>}, _}, execute(admin, #{}, undefined)).
   92: 
   93: can_connect_to_domain_admin(_Config) ->
   94:     ?assertMatch({{<<"400">>, <<"Bad Request">>}, _}, execute(domain_admin, #{}, undefined)).
   95: 
   96: can_connect_to_user(_Config) ->
   97:     ?assertMatch({{<<"400">>, <<"Bad Request">>}, _}, execute(user, #{}, undefined)).
   98: 
   99: can_load_graphiql(Config) ->
  100:     Ep = ?config(schema_endpoint, Config),
  101:     {Status, Html} = get_graphiql_website(Ep),
  102:     ?assertEqual({<<"200">>, <<"OK">>}, Status),
  103:     ?assertNotEqual(nomatch, binary:match(Html, <<"Loading...">>)).
  104: 
  105: user_checks_auth(Config) ->
  106:     Ep = ?config(schema_endpoint, Config),
  107:     StatusData = execute(Ep, user_check_auth_body(), undefined),
  108:     ?assertUserAuth(null, 'UNAUTHORIZED', StatusData).
  109: 
  110: auth_user_checks_auth(Config) ->
  111:     escalus:fresh_story(
  112:         Config, [{alice, 1}],
  113:         fun(Alice) ->
  114:             AliceJID = escalus_utils:jid_to_lower(escalus_client:short_jid(Alice)),
  115:             StatusData = execute_user(user_check_auth_body(), Alice, Config),
  116:             ?assertUserAuth(AliceJID, 'AUTHORIZED', StatusData)
  117:         end).
  118: 
  119: admin_checks_auth(Config) ->
  120:     Ep = ?config(schema_endpoint, Config),
  121:     StatusData = execute(Ep, admin_check_auth_body(), undefined),
  122:     ?assertAdminAuth(null, null, 'UNAUTHORIZED', StatusData).
  123: 
  124: auth_admin_checks_auth(Config) ->
  125:     StatusData = execute_auth(admin_check_auth_body(), Config),
  126:     ?assertAdminAuth(null, 'ADMIN', 'AUTHORIZED', StatusData).
  127: 
  128: domain_admin_checks_auth(Config) ->
  129:     Ep = ?config(schema_endpoint, Config),
  130:     Res = execute(Ep, admin_check_auth_body(), undefined),
  131:     ?assertAdminAuth(null, null, 'UNAUTHORIZED', Res).
  132: 
  133: auth_domain_admin_checks_auth(Config) ->
  134:     {Username, _} = ?config(domain_admin, Config),
  135:     Domain = escalus_utils:get_server(Username),
  136:     Res = execute_domain_auth(admin_check_auth_body(), Config),
  137:     ?assertAdminAuth(Domain, 'DOMAIN_ADMIN', 'AUTHORIZED', Res).
  138: 
  139: %% Helpers
  140: 
  141: assert_auth(Auth, {Status, Data}) ->
  142:     ?assertEqual({<<"200">>, <<"OK">>}, Status),
  143:     ?assertMatch(#{<<"data">> := #{<<"checkAuth">> := Auth}}, Data).
  144: 
  145: get_graphiql_website(EpName) ->
  146:     Request =
  147:       #{port => graphql_helper:get_listener_port(EpName),
  148:         role => {graphql, atom_to_binary(EpName)},
  149:         method => <<"GET">>,
  150:         headers => [{<<"Accept">>, <<"text/html">>}],
  151:         return_maps => true,
  152:         path => "/graphql"},
  153:     rest_helper:make_request(Request).
  154: 
  155: maybe_atom_to_bin(null) -> null;
  156: maybe_atom_to_bin(X) -> atom_to_binary(X).
  157: 
  158: admin_check_auth_body() ->
  159:     #{query => "{ checkAuth { domain authType authStatus } }"}.
  160: 
  161: user_check_auth_body() ->
  162:     #{query => "{ checkAuth { username authStatus } }"}.