Skip to content

Commit

Permalink
Changing cowboy_handler and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Janusz Jakubiec authored and Janusz Jakubiec committed Oct 24, 2022
1 parent a9ee17f commit 4db0b32
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 14 deletions.
30 changes: 28 additions & 2 deletions big_tests/tests/graphql_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ all() ->
[{group, cowboy_handler},
{group, admin_handler},
{group, domain_admin_handler},
{group, user_handler}].
{group, user_handler},
{group, categories_disabled}].

groups() ->
[{cowboy_handler, [parallel], cowboy_handler()},
{user_handler, [parallel], user_handler()},
{domain_admin_handler, [parallel], domain_admin_handler()},
{admin_handler, [parallel], admin_handler()}].
{admin_handler, [parallel], admin_handler()},
{categories_disabled, [parallel], categories_disabled_tests()}].

cowboy_handler() ->
[can_connect_to_admin,
Expand All @@ -50,6 +52,10 @@ domain_admin_handler() ->
common_tests() ->
[can_load_graphiql].

categories_disabled_tests() ->
[category_disabled_error_test,
admin_checks_auth].

init_per_suite(Config) ->
Config1 = escalus:init_per_suite(Config),
dynamic_modules:save_modules(domain_helper:host_type(), Config1).
Expand All @@ -71,13 +77,26 @@ init_per_group(domain_admin_handler, Config) ->
init_per_group(user_handler, Config) ->
Config1 = escalus:create_users(Config, escalus:get_users([alice])),
[{schema_endpoint, user} | Config1];
init_per_group(categories_disabled, Config) ->
#{node := Node} = mim(),
CowboyGraphqlListenerConfig = graphql_helper:get_listener_config(Node, admin),
#{handlers := [SchemaConfig]} = CowboyGraphqlListenerConfig,
UpdatedSchemaConfig = maps:put(allowed_categories, [<<"vcard">>, <<"checkAuth">>], SchemaConfig),
UpdatedListenerConfig = maps:put(handlers, [UpdatedSchemaConfig], CowboyGraphqlListenerConfig),
mongoose_helper:restart_listener(mim(), UpdatedListenerConfig),
Config1 = [{admin_listener_config, CowboyGraphqlListenerConfig} | Config],
graphql_helper:init_admin_handler(Config1);
init_per_group(cowboy_handler, Config) ->
Config.

end_per_group(user_handler, Config) ->
escalus:delete_users(Config, escalus:get_users([alice]));
end_per_group(domain_admin_handler, Config) ->
graphql_helper:end_domain_admin_handler(Config);
end_per_group(categories_disabled, Config) ->
ListenerConfig = ?config(admin_listener_config, Config),
mongoose_helper:restart_listener(mim(), ListenerConfig),
Config;
end_per_group(_, _Config) ->
ok.

Expand Down Expand Up @@ -136,6 +155,10 @@ auth_domain_admin_checks_auth(Config) ->
Res = execute_auth(admin_check_auth_body(), Config),
?assertAdminAuth(Domain, 'DOMAIN_ADMIN', 'AUTHORIZED', Res).

category_disabled_error_test(Config) ->
Ep = ?config(schema_endpoint, Config),
StatusData = execute(Ep, admin_server_get_loglevel_body(), undefined).

%% Helpers

assert_auth(Auth, {Status, Data}) ->
Expand All @@ -158,5 +181,8 @@ maybe_atom_to_bin(X) -> atom_to_binary(X).
admin_check_auth_body() ->
#{query => "{ checkAuth { domain authType authStatus } }"}.

admin_server_get_loglevel_body() ->
#{query => "{ server { getLogLevel } }"}.

user_check_auth_body() ->
#{query => "{ checkAuth { username authStatus } }"}.
1 change: 1 addition & 0 deletions src/graphql/mongoose_graphql.erl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
-export([init/0,
get_endpoint/1,
create_endpoint/3,
graphql_parse/1,
execute/2,
execute/3,
execute_cli/3]).
Expand Down
47 changes: 36 additions & 11 deletions src/graphql/mongoose_graphql_cowboy_handler.erl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
-ignore_xref([from_json/2, to_html/2, to_json/2]).

-include("mongoose_config_spec.hrl").
-include_lib("graphql/src/graphql_internal.hrl").
-include_lib("graphql/src/graphql_schema.hrl").

%% mongoose_http_handler callbacks

Expand All @@ -43,8 +45,9 @@ config_spec() ->
items = #{<<"username">> => #option{type = binary},
<<"password">> => #option{type = binary},
<<"schema_endpoint">> => #option{type = atom,
validate = {enum, [admin, domain_admin, user]}}
},
validate = {enum, [admin, domain_admin, user]}},
<<"allowed_categories">> => #list{items = #option{type = binary,
validate = {enum, allowed_schemas()}}}},
format_items = map,
required = [<<"schema_endpoint">>],
process = fun ?MODULE:process_config/1}.
Expand Down Expand Up @@ -172,20 +175,36 @@ auth_domain_admin(_, State) ->
run_request(#{document := undefined}, Req, State) ->
reply_error(make_error(decode, no_query_supplied), Req, State);
run_request(#{} = ReqCtx, Req, #{schema_endpoint := EpName,
authorized := AuthStatus} = State) ->
authorized := AuthStatus,
llowed_categories := AllowedCategories} = State) ->
AllowedCategories = maps:get(allowed_categories, State, []),
Ep = mongoose_graphql:get_endpoint(EpName),
Ctx = maps:get(schema_ctx, State, #{}),
ReqCtx2 = ReqCtx#{authorized => AuthStatus, ctx => Ctx#{method => http}},
case mongoose_graphql:execute(Ep, ReqCtx2) of
{ok, Response} ->
ResponseBody = mongoose_graphql_response:term_to_json(Response),
Req2 = cowboy_req:set_resp_body(ResponseBody, Req),
Reply = cowboy_req:reply(200, Req2),
{stop, Reply, State};
{error, Reason} ->
reply_error(Reason, Req, State)
Category = retrieve_category_from_ctx(ReqCtx),
case AllowedCategories =:= [] orelse lists:member(Category, AllowedCategories) of
true ->
case mongoose_graphql:execute(Ep, ReqCtx2) of
{ok, Response} ->
ResponseBody = mongoose_graphql_response:term_to_json(Response),
Req2 = cowboy_req:set_resp_body(ResponseBody, Req),
Reply = cowboy_req:reply(200, Req2),
{stop, Reply, State};
{error, Reason} ->
reply_error(Reason, Req, State)
end;
false ->
reply_error({category_disabled, Category}, Req, State)
end.

retrieve_category_from_ctx(Ctx)->
#{document := Doc} = Ctx,
{ok, Document} = mongoose_graphql:graphql_parse(Doc),
[Parsed] = Document#document.definitions,
[Field] = Parsed#op.selection_set,
{name, _, Category} = Field#field.id,
Category.

gather(Req) ->
{ok, Body, Req2} = cowboy_req:read_body(Req),
Bindings = cowboy_req:bindings(Req2),
Expand Down Expand Up @@ -250,3 +269,9 @@ reply_error(Msg, Req, State) ->
Req2 = cowboy_req:set_resp_body(Body, Req),
Reply = cowboy_req:reply(Code, Req2),
{stop, Reply, State}.

allowed_schemas() ->
[<<"checkAuth">>, <<"account">>, <<"domain">>, <<"last">>, <<"muc">>, <<"muc_light">>,
<<"session">>, <<"stanza">>, <<"roster">>, <<"vcard">>, <<"private">>, <<"metric">>,
<<"stat">>, <<"gdpr">>, <<"mnesia">>, <<"server">>, <<"inbox">>, <<"http_upload">>,
<<"offline">>, <<"token">>].
4 changes: 4 additions & 0 deletions src/graphql/mongoose_graphql_errors.erl
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ format_error(internal_crash) ->
Msg = #{message => <<"GraphQL Internal Server Error">>,
extensions => #{code => internal_server_error}},
{500, Msg};
format_error({{category_disabled, Category}}) ->
Message = iolist_to_binary(io_lib:format("~p", [
#{message => <<"Category disabled">>, extensions => #{category => Category}}])),
{400, #{message => Message, extensions => #{code => category_disabled}}};
format_error(Err) ->
Msg = #{extensions => #{code => uncategorized},
message => iolist_to_binary(io_lib:format("~p", [Err]))},
Expand Down
3 changes: 2 additions & 1 deletion test/common/config_parser_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1084,7 +1084,8 @@ default_config([listen, http, handlers, mongoose_client_api]) ->
module => mongoose_client_api};
default_config([listen, http, handlers, mongoose_graphql_cowboy_handler]) ->
#{module => mongoose_graphql_cowboy_handler,
schema_endpoint => admin};
schema_endpoint => admin,
allowed_categories => []};
default_config([listen, http, handlers, Module]) ->
#{module => Module};
default_config([listen, http, transport]) ->
Expand Down
3 changes: 3 additions & 0 deletions test/config_parser_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,9 @@ listen_http_handlers_graphql(_Config) ->
T = fun graphql_handler_raw/1,
{P, _} = test_listen_http_handler(mongoose_graphql_cowboy_handler, T),
test_listen_http_handler_creds(P, T),
?cfg(P ++ [allowed_categories], [<<"muc">>, <<"inbox">>],
T(#{<<"allowed_categories">> => [<<"muc">>, <<"inbox">>]})),
?err(T(#{<<"allowed_categories">> => [<<"invalid">>]})),
?err(T(#{<<"schema_endpoint">> => <<"wrong_endpoint">>})),
?err(http_handler_raw(mongoose_graphql_cowboy_handler, #{})).

Expand Down

0 comments on commit 4db0b32

Please sign in to comment.