Skip to content

Commit

Permalink
Merge pull request #3648 from esl/graphql/use-enum-in-handler-config
Browse files Browse the repository at this point in the history
GraphQL - Use enum in cowboy handler configuration and provide test
  • Loading branch information
arcusfelis authored May 25, 2022
2 parents d3cc423 + 301af23 commit 66f476b
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 19 deletions.
8 changes: 4 additions & 4 deletions big_tests/tests/graphql_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
execute(EpName, Body, Creds) ->
Request =
#{port => get_listener_port(EpName),
role => {graphql, atom_to_binary(EpName)},
role => {graphql, EpName},
method => <<"POST">>,
return_maps => true,
creds => Creds,
Expand Down Expand Up @@ -123,9 +123,9 @@ get_value([Field | Fields], Data) ->
Data2 = maps:get(BinField, Data),
get_value(Fields, Data2).

is_graphql_config(#{module := ejabberd_cowboy, handlers := Handlers}, EpName) ->
lists:any(fun(#{module := mongoose_graphql_cowboy_handler, schema_endpoint := EpBin}) ->
atom_to_binary(EpName) =:= EpBin;
is_graphql_config(#{module := ejabberd_cowboy, handlers := Handlers}, ExpEpName) ->
lists:any(fun(#{module := mongoose_graphql_cowboy_handler, schema_endpoint := EpName}) ->
ExpEpName =:= EpName;
(_) -> false
end, Handlers);
is_graphql_config(_, _EpName) ->
Expand Down
23 changes: 13 additions & 10 deletions src/graphql/mongoose_graphql_cowboy_handler.erl
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,15 @@

-spec config_spec() -> mongoose_config_spec:config_section().
config_spec() ->
#section{items = #{<<"username">> => #option{type = binary},
<<"password">> => #option{type = binary},
<<"schema_endpoint">> => #option{type = binary}},
format_items = map,
required = [<<"schema_endpoint">>],
process = fun ?MODULE:process_config/1}.
#section{
items = #{<<"username">> => #option{type = binary},
<<"password">> => #option{type = binary},
<<"schema_endpoint">> => #option{type = atom,
validate = {enum, [admin, domain_admin, user]}}
},
format_items = map,
required = [<<"schema_endpoint">>],
process = fun ?MODULE:process_config/1}.

process_config(Opts) ->
case maps:is_key(username, Opts) =:= maps:is_key(password, Opts) of
Expand Down Expand Up @@ -118,11 +121,11 @@ to_json(Req, State) -> json_request(Req, State).

%% Internal

check_auth(Auth, #{schema_endpoint := <<"domain_admin">>} = State) ->
check_auth(Auth, #{schema_endpoint := domain_admin} = State) ->
auth_domain_admin(Auth, State);
check_auth(Auth, #{schema_endpoint := <<"admin">>} = State) ->
check_auth(Auth, #{schema_endpoint := admin} = State) ->
auth_admin(Auth, State);
check_auth(Auth, #{schema_endpoint := <<"user">>} = State) ->
check_auth(Auth, #{schema_endpoint := user} = State) ->
auth_user(Auth, State).

auth_user({basic, User, Password}, State) ->
Expand Down Expand Up @@ -170,7 +173,7 @@ 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) ->
Ep = mongoose_graphql:get_endpoint(binary_to_existing_atom(EpName)),
Ep = mongoose_graphql:get_endpoint(EpName),
Ctx = maps:get(schema_ctx, State, #{}),
ReqCtx2 = ReqCtx#{authorized => AuthStatus, ctx => Ctx},
case mongoose_graphql:execute(Ep, ReqCtx2) of
Expand Down
3 changes: 3 additions & 0 deletions test/common/config_parser_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,9 @@ default_config([listen, http, handlers, mongoose_client_api]) ->
default_config([listen, http, handlers, mongoose_api]) ->
#{handlers => [mongoose_api_metrics, mongoose_api_users],
module => mongoose_api};
default_config([listen, http, handlers, mongoose_graphql_cowboy_handler]) ->
#{module => mongoose_graphql_cowboy_handler,
schema_endpoint => admin};
default_config([listen, http, handlers, Module]) ->
#{module => Module};
default_config([listen, http, transport]) ->
Expand Down
17 changes: 16 additions & 1 deletion test/config_parser_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ groups() ->
listen_http_handlers_api,
listen_http_handlers_api_admin,
listen_http_handlers_api_client,
listen_http_handlers_domain]},
listen_http_handlers_domain,
listen_http_handlers_graphql]},
{auth, [parallel], [auth_methods,
auth_password,
auth_sasl_external,
Expand Down Expand Up @@ -680,6 +681,13 @@ listen_http_handlers_domain(_Config) ->
{P, T} = test_listen_http_handler(mongoose_domain_handler),
test_listen_http_handler_creds(P, T).

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),
?err(T(#{<<"schema_endpoint">> => <<"wrong_endpoint">>})),
?err(http_handler_raw(mongoose_graphql_cowboy_handler, #{})).

test_listen_http_handler_creds(P, T) ->
CredsRaw = #{<<"username">> => <<"user">>, <<"password">> => <<"pass">>},
?cfg(P ++ [username], <<"user">>, T(CredsRaw)),
Expand All @@ -691,6 +699,9 @@ test_listen_http_handler_creds(P, T) ->

test_listen_http_handler(Module) ->
T = fun(Opts) -> http_handler_raw(Module, Opts) end,
test_listen_http_handler(Module, T).

test_listen_http_handler(Module, T) ->
P = [listen, 1, handlers, 1],
?cfg(P, config([listen, http, handlers, Module], #{host => "localhost", path => "/api"}),
T(#{})),
Expand Down Expand Up @@ -3051,6 +3062,10 @@ check_module_defaults(Mod) ->
listener(Type, Opts) ->
config([listen, Type], Opts).

graphql_handler_raw(Opts) ->
http_handler_raw(mongoose_graphql_cowboy_handler,
maps:merge(#{<<"schema_endpoint">> => <<"admin">>}, Opts)).

http_handler_raw(Type, Opts) ->
MergedOpts = maps:merge(#{<<"host">> => <<"localhost">>, <<"path">> => <<"/api">>}, Opts),
listen_raw(http, #{<<"port">> => 5280,
Expand Down
8 changes: 4 additions & 4 deletions test/mongoose_graphql_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,12 @@ init_per_group(user_listener, Config) ->
(#jid{luser = <<"alice">>}, <<"makota">>) -> {true, {}};
(_, _) -> false
end),
ListenerOpts = #{schema_endpoint => <<"user">>},
ListenerOpts = #{schema_endpoint => user},
init_ep_listener(5557, user_schema_ep, ListenerOpts, Config);
init_per_group(admin_listener, Config) ->
ListenerOpts = #{username => <<"admin">>,
password => <<"secret">>,
schema_endpoint => <<"admin">>},
schema_endpoint => admin},
init_ep_listener(5558, admin_schema_ep, ListenerOpts, Config);
init_per_group(domain_admin_listener, Config) ->
meck:new(mongoose_domain_api, [no_link]),
Expand All @@ -168,7 +168,7 @@ init_per_group(domain_admin_listener, Config) ->
end),
meck:expect(mongoose_domain_api, get_subdomain_info,
fun (_) -> {error, not_found} end),
ListenerOpts = #{schema_endpoint => <<"domain_admin">>},
ListenerOpts = #{schema_endpoint => domain_admin},
init_ep_listener(5560, domain_admin_schema_ep, ListenerOpts, Config);
init_per_group(domain_permissions, Config) ->
meck:new(mongoose_domain_api, [no_link]),
Expand Down Expand Up @@ -657,7 +657,7 @@ auth_user_can_access_protected_types(Config) ->
no_creds_defined_admin_can_access_protected(_Config) ->
Port = 5559,
Ep = "http://localhost:" ++ integer_to_list(Port),
start_listener(no_creds_admin_listener, Port, #{schema_endpoint => <<"admin">>}),
start_listener(no_creds_admin_listener, Port, #{schema_endpoint => admin}),
Body = #{<<"query">> => <<"{ field }">>},
{Status, Data} = execute(Ep, Body, undefined),
assert_access_granted(Status, Data).
Expand Down

0 comments on commit 66f476b

Please sign in to comment.