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_user/3, 11: get_value/2, get_bad_request/1]). 12: 13: -define(assertAdminAuth(Domain, Type, Auth, Data), 14: assert_auth(#{<<"domain">> => Domain, 15: <<"authStatus">> => atom_to_binary(Auth), 16: <<"authType">> => maybe_atom_to_bin(Type)}, Data)). 17: -define(assertUserAuth(Username, Auth, Data), 18: assert_auth(#{<<"username">> => Username, 19: <<"authStatus">> => atom_to_binary(Auth)}, Data)). 20: 21: suite() -> 22: require_rpc_nodes([mim]) ++ escalus:suite(). 23: 24: all() -> 25: [{group, cowboy_handler}, 26: {group, admin_handler}, 27: {group, domain_admin_handler}, 28: {group, user_handler}, 29: {group, categories_disabled}]. 30: 31: groups() -> 32: [{cowboy_handler, [parallel], cowboy_handler()}, 33: {user_handler, [parallel], user_handler()}, 34: {domain_admin_handler, [parallel], domain_admin_handler()}, 35: {admin_handler, [parallel], admin_handler()}, 36: {categories_disabled, [parallel], categories_disabled_tests()}]. 37: 38: cowboy_handler() -> 39: [can_connect_to_admin, 40: can_connect_to_domain_admin, 41: can_connect_to_user]. 42: 43: user_handler() -> 44: [user_checks_auth, 45: auth_user_checks_auth | common_tests()]. 46: admin_handler() -> 47: [admin_checks_auth, 48: auth_admin_checks_auth | common_tests()]. 49: domain_admin_handler() -> 50: [domain_admin_checks_auth, 51: auth_domain_admin_checks_auth | common_tests()]. 52: 53: common_tests() -> 54: [can_load_graphiql]. 55: 56: categories_disabled_tests() -> 57: [category_disabled_error_test, 58: admin_checks_auth, 59: category_does_not_exist_error, 60: listener_reply_with_validation_error, 61: multiple_categories_query_test]. 62: 63: init_per_suite(Config) -> 64: Config1 = escalus:init_per_suite(Config), 65: dynamic_modules:save_modules(domain_helper:host_type(), Config1). 66: 67: end_per_suite(Config) -> 68: dynamic_modules:restore_modules(Config), 69: escalus_fresh:clean(), 70: escalus:end_per_suite(Config). 71: 72: init_per_group(admin_handler, Config) -> 73: graphql_helper:init_admin_handler(Config); 74: init_per_group(domain_admin_handler, Config) -> 75: case mongoose_helper:is_rdbms_enabled(domain_helper:host_type()) of 76: true -> 77: graphql_helper:init_domain_admin_handler(Config); 78: false -> 79: {skip, require_rdbms} 80: end; 81: init_per_group(user_handler, Config) -> 82: Config1 = escalus:create_users(Config, escalus:get_users([alice])), 83: [{schema_endpoint, user} | Config1]; 84: init_per_group(categories_disabled, Config) -> 85: #{node := Node} = mim(), 86: CowboyGraphqlListenerConfig = graphql_helper:get_listener_config(Node, admin), 87: #{handlers := [SchemaConfig]} = CowboyGraphqlListenerConfig, 88: UpdatedSchemaConfig = maps:put(allowed_categories, [<<"vcard">>, <<"checkAuth">>], SchemaConfig), 89: UpdatedListenerConfig = maps:put(handlers, [UpdatedSchemaConfig], CowboyGraphqlListenerConfig), 90: mongoose_helper:restart_listener(mim(), UpdatedListenerConfig), 91: Config1 = [{admin_listener_config, CowboyGraphqlListenerConfig} | Config], 92: graphql_helper:init_admin_handler(Config1); 93: init_per_group(cowboy_handler, Config) -> 94: Config. 95: 96: end_per_group(user_handler, Config) -> 97: escalus:delete_users(Config, escalus:get_users([alice])); 98: end_per_group(domain_admin_handler, Config) -> 99: graphql_helper:end_domain_admin_handler(Config); 100: end_per_group(categories_disabled, Config) -> 101: ListenerConfig = ?config(admin_listener_config, Config), 102: mongoose_helper:restart_listener(mim(), ListenerConfig), 103: Config; 104: end_per_group(_, _Config) -> 105: ok. 106: 107: init_per_testcase(CaseName, Config) -> 108: escalus:init_per_testcase(CaseName, Config). 109: 110: end_per_testcase(CaseName, Config) -> 111: escalus:end_per_testcase(CaseName, Config). 112: 113: can_connect_to_admin(_Config) -> 114: ?assertMatch({{<<"400">>, <<"Bad Request">>}, _}, execute(admin, #{}, undefined)). 115: 116: can_connect_to_domain_admin(_Config) -> 117: ?assertMatch({{<<"400">>, <<"Bad Request">>}, _}, execute(domain_admin, #{}, undefined)). 118: 119: can_connect_to_user(_Config) -> 120: ?assertMatch({{<<"400">>, <<"Bad Request">>}, _}, execute(user, #{}, undefined)). 121: 122: can_load_graphiql(Config) -> 123: Ep = ?config(schema_endpoint, Config), 124: {Status, Html} = get_graphiql_website(Ep), 125: ?assertEqual({<<"200">>, <<"OK">>}, Status), 126: ?assertNotEqual(nomatch, binary:match(Html, <<"Loading...">>)). 127: 128: user_checks_auth(Config) -> 129: Ep = ?config(schema_endpoint, Config), 130: StatusData = execute(Ep, user_check_auth_body(), undefined), 131: ?assertUserAuth(null, 'UNAUTHORIZED', StatusData). 132: 133: auth_user_checks_auth(Config) -> 134: escalus:fresh_story( 135: Config, [{alice, 1}], 136: fun(Alice) -> 137: AliceJID = escalus_utils:jid_to_lower(escalus_client:short_jid(Alice)), 138: StatusData = execute_user(user_check_auth_body(), Alice, Config), 139: ?assertUserAuth(AliceJID, 'AUTHORIZED', StatusData) 140: end). 141: 142: admin_checks_auth(Config) -> 143: Ep = ?config(schema_endpoint, Config), 144: StatusData = execute(Ep, admin_check_auth_body(), undefined), 145: ?assertAdminAuth(null, null, 'UNAUTHORIZED', StatusData). 146: 147: auth_admin_checks_auth(Config) -> 148: StatusData = execute_auth(admin_check_auth_body(), Config), 149: ?assertAdminAuth(null, 'ADMIN', 'AUTHORIZED', StatusData). 150: 151: domain_admin_checks_auth(Config) -> 152: Ep = ?config(schema_endpoint, Config), 153: Res = execute(Ep, admin_check_auth_body(), undefined), 154: ?assertAdminAuth(null, null, 'UNAUTHORIZED', Res). 155: 156: auth_domain_admin_checks_auth(Config) -> 157: {Username, _} = ?config(domain_admin, Config), 158: Domain = escalus_utils:get_server(Username), 159: Res = execute_auth(admin_check_auth_body(), Config), 160: ?assertAdminAuth(Domain, 'DOMAIN_ADMIN', 'AUTHORIZED', Res). 161: 162: category_disabled_error_test(Config) -> 163: Status = execute_auth(admin_server_get_loglevel_body(), Config), 164: {_Code, #{<<"errors">> := [Msg]}} = Status, 165: ?assertEqual(<<"category_disabled">>, get_value([extensions, code], Msg)), 166: ?assertEqual([<<"server">>], get_value([path], Msg)). 167: 168: category_does_not_exist_error(Config) -> 169: Ep = ?config(schema_endpoint, Config), 170: Status = execute(Ep, #{<<"query">> => <<"{ field ">>}, undefined), 171: get_bad_request(Status), 172: {_Code, #{<<"errors">> := [Msg]}} = Status, 173: ?assertEqual(<<"parser_error">>, get_value([extensions, code], Msg)). 174: 175: listener_reply_with_validation_error(Config) -> 176: Ep = ?config(schema_endpoint, Config), 177: Body = #{<<"query">> => <<"query Q1 { field } query Q1 { field }">>, 178: <<"operationName">> => <<"Q1">>}, 179: {Status, Data} = execute(Ep, Body, undefined). 180: 181: multiple_categories_query_test(Config) -> 182: Status = execute_auth(user_check_auth_multiple(), Config), 183: {_Code, #{<<"errors">> := [ErrorMsg], <<"data">> := DataMsg}} = Status, 184: ?assertEqual(<<"category_disabled">>, get_value([extensions, code], ErrorMsg)), 185: ?assertEqual([<<"server">>], get_value([path], ErrorMsg)), 186: ?assertEqual(<<"AUTHORIZED">>, get_value([checkAuth, authStatus], DataMsg)). 187: 188: %% Helpers 189: 190: assert_auth(Auth, {Status, Data}) -> 191: ?assertEqual({<<"200">>, <<"OK">>}, Status), 192: ?assertMatch(#{<<"data">> := #{<<"checkAuth">> := Auth}}, Data). 193: 194: get_graphiql_website(EpName) -> 195: Request = 196: #{port => graphql_helper:get_listener_port(EpName), 197: role => {graphql, atom_to_binary(EpName)}, 198: method => <<"GET">>, 199: headers => [{<<"Accept">>, <<"text/html">>}], 200: return_maps => true, 201: path => "/graphql"}, 202: rest_helper:make_request(Request). 203: 204: maybe_atom_to_bin(null) -> null; 205: maybe_atom_to_bin(X) -> atom_to_binary(X). 206: 207: admin_check_auth_body() -> 208: #{query => "{ checkAuth { domain authType authStatus } }"}. 209: 210: admin_server_get_loglevel_body() -> 211: #{query => "{ server { getLoglevel } }"}. 212: 213: user_check_auth_body() -> 214: #{query => "{ checkAuth { username authStatus } }"}. 215: 216: user_check_auth_multiple() -> 217: #{query => "{ checkAuth { authStatus } server { getLoglevel } }"}.