Skip to content

Commit

Permalink
Wip4
Browse files Browse the repository at this point in the history
  • Loading branch information
Premwoik committed Apr 25, 2022
1 parent 2eeda37 commit 6127638
Show file tree
Hide file tree
Showing 18 changed files with 196 additions and 59 deletions.
8 changes: 8 additions & 0 deletions big_tests/tests/domain_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
delete_configured_domains/0,
insert_domain/3,
delete_domain/2,
set_domain_password/3,
delete_domain_password/2,
make_metrics_prefix/1,
host_types/0,
host_types/1,
Expand Down Expand Up @@ -66,6 +68,12 @@ insert_persistent_domain(Node, Domain, HostType) ->
delete_persistent_domain(Node, Domain, HostType) ->
ok = rpc(Node, mongoose_domain_api, delete_domain, [Domain, HostType]).

set_domain_password(Node, Domain, Password) ->
ok = rpc(Node, mongoose_domain_api, set_domain_password, [Domain, Password]).

delete_domain_password(Node, Domain) ->
ok = rpc(Node, mongoose_domain_api, delete_domain_password, [Domain]).

for_each_configured_domain(F) ->
[for_each_configured_domain(F, Opts) || {_, Opts} <- ct:get_config(hosts)],
ok.
Expand Down
69 changes: 45 additions & 24 deletions big_tests/tests/graphql_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,33 @@
-compile([export_all, nowarn_export_all]).

-import(distributed_helper, [mim/0, require_rpc_nodes/1, rpc/4]).
-import(graphql_helper, [execute/3]).
-import(graphql_helper, [execute/3, execute_auth/2, execute_domain_auth/2, execute_user/3]).

-define(assertAdminAuth(Auth, Data), assert_auth(atom_to_binary(Auth), Data)).
-define(assertAdminAuth(Domain, Type, Auth, Data),
assert_auth(#{<<"domain">> => Domain,
<<"authStatus">> => atom_to_binary(Auth),
<<"authType">> => maybe_atom_to_bin(Type)}, Data)).
-define(assertUserAuth(Username, Auth, Data),
assert_auth(#{<<"username">> => Username,
<<"authStatus">> => atom_to_binary(Auth)}, Data)).

suite() ->
require_rpc_nodes([mim]) ++ escalus:suite().

all() ->
[{group, cowboy_handler},
{group, admin_handler},
{group, domain_admin_handler},
{group, user_handler}].

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

cowboy_handler() ->
[can_connect_to_admin,
can_connect_to_domain_admin,
can_connect_to_user].

user_handler() ->
Expand All @@ -37,6 +42,9 @@ user_handler() ->
admin_handler() ->
[admin_checks_auth,
auth_admin_checks_auth | common_tests()].
domain_admin_handler() ->
[domain_admin_checks_auth,
auth_domain_admin_checks_auth | common_tests()].

common_tests() ->
[can_load_graphiql].
Expand All @@ -52,14 +60,18 @@ end_per_suite(Config) ->

init_per_group(admin_handler, Config) ->
graphql_helper:init_admin_handler(Config);
init_per_group(domain_admin_handler, Config) ->
graphql_helper:init_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(_, Config) ->
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(_, _Config) ->
ok.

Expand All @@ -72,6 +84,9 @@ end_per_testcase(CaseName, Config) ->
can_connect_to_admin(_Config) ->
?assertMatch({{<<"400">>, <<"Bad Request">>}, _}, execute(admin, #{}, undefined)).

can_connect_to_domain_admin(_Config) ->
?assertMatch({{<<"400">>, <<"Bad Request">>}, _}, execute(domain_admin, #{}, undefined)).

can_connect_to_user(_Config) ->
?assertMatch({{<<"400">>, <<"Bad Request">>}, _}, execute(user, #{}, undefined)).

Expand All @@ -83,47 +98,44 @@ can_load_graphiql(Config) ->

user_checks_auth(Config) ->
Ep = ?config(schema_endpoint, Config),
Body = #{query => "{ checkAuth { username authStatus } }"},
StatusData = execute(Ep, Body, undefined),
StatusData = execute(Ep, user_check_auth_body(), undefined),
?assertUserAuth(null, 'UNAUTHORIZED', StatusData).

auth_user_checks_auth(Config) ->
escalus:fresh_story(
Config, [{alice, 1}],
fun(Alice) ->
Password = user_password(alice),
AliceJID = escalus_client:short_jid(Alice),
Ep = ?config(schema_endpoint, Config),
Body = #{query => "{ checkAuth { username authStatus } }"},
StatusData = execute(Ep, Body, {AliceJID, Password}),
AliceJID = escalus_utils:jid_to_lower(escalus_client:short_jid(Alice)),
StatusData = execute_user(user_check_auth_body(), Alice, Config),
?assertUserAuth(AliceJID, 'AUTHORIZED', StatusData)
end).

admin_checks_auth(Config) ->
Ep = ?config(schema_endpoint, Config),
Body = #{query => "{ checkAuth }"},
StatusData = execute(Ep, Body, undefined),
?assertAdminAuth('UNAUTHORIZED', StatusData).
StatusData = execute(Ep, admin_check_auth_body(), undefined),
?assertAdminAuth(null, null, 'UNAUTHORIZED', StatusData).

auth_admin_checks_auth(Config) ->
StatusData = execute_auth(admin_check_auth_body(), Config),
?assertAdminAuth(null, 'ADMIN', 'AUTHORIZED', StatusData).

domain_admin_checks_auth(Config) ->
Ep = ?config(schema_endpoint, Config),
Opts = ?config(listener_opts, Config),
User = proplists:get_value(username, Opts),
Password = proplists:get_value(password, Opts),
Body = #{query => "{ checkAuth }"},
StatusData = execute(Ep, Body, {User, Password}),
?assertAdminAuth('AUTHORIZED', StatusData).
Res = execute(Ep, admin_check_auth_body(), undefined),
?assertAdminAuth(null, null, 'UNAUTHORIZED', Res).

auth_domain_admin_checks_auth(Config) ->
{Username, _} = ?config(domain_admin, Config),
Domain = escalus_utils:get_server(Username),
Res = execute_domain_auth(admin_check_auth_body(), Config),
?assertAdminAuth(Domain, 'DOMAIN_ADMIN', 'AUTHORIZED', Res).

%% Helpers

assert_auth(Auth, {Status, Data}) ->
?assertEqual({<<"200">>, <<"OK">>}, Status),
?assertMatch(#{<<"data">> := #{<<"checkAuth">> := Auth}}, Data).

user_password(User) ->
[{User, Props}] = escalus:get_users([User]),
proplists:get_value(password, Props).

get_graphiql_website(EpName) ->
Request =
#{port => graphql_helper:get_listener_port(EpName),
Expand All @@ -133,3 +145,12 @@ get_graphiql_website(EpName) ->
return_maps => true,
path => "/graphql"},
rest_helper:make_request(Request).

maybe_atom_to_bin(null) -> null;
maybe_atom_to_bin(X) -> atom_to_binary(X).

admin_check_auth_body() ->
#{query => "{ checkAuth { domain authType authStatus } }"}.

user_check_auth_body() ->
#{query => "{ checkAuth { username authStatus } }"}.
22 changes: 20 additions & 2 deletions big_tests/tests/graphql_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

-import(distributed_helper, [mim/0, rpc/4]).

-export([execute/3, execute_auth/2, execute_user/3, get_listener_port/1, get_listener_config/1]).
-export([init_admin_handler/1]).
-export([execute/3, execute_auth/2, execute_domain_auth/2, execute_user/3]).
-export([init_admin_handler/1, init_domain_admin_handler/1, end_domain_admin_handler/1]).
-export([get_listener_port/1, get_listener_config/1]).
-export([get_ok_value/2, get_err_msg/1, get_err_msg/2, make_creds/1,
user_to_bin/1, user_to_jid/1, user_to_full_bin/1]).

Expand All @@ -30,6 +31,11 @@ execute_auth(Body, Config) ->
Password = proplists:get_value(password, Opts),
execute(Ep, Body, {User, Password}).

execute_domain_auth(Body, Config) ->
Ep = ?config(schema_endpoint, Config),
Creds = ?config(domain_admin, Config),
execute(Ep, Body, Creds).

execute_user(Body, User, Config) ->
Ep = ?config(schema_endpoint, Config),
Creds = make_creds(User),
Expand Down Expand Up @@ -57,6 +63,18 @@ init_admin_handler(Config) ->
ct:fail(<<"Admin credentials are not defined in config">>)
end.

init_domain_admin_handler(Config) ->
Domain = domain_helper:domain(),
Password = base16:encode(crypto:strong_rand_bytes(8)),
Creds = {<<"admin@", Domain/binary>>, Password},
ok = domain_helper:set_domain_password(mim(), Domain, Password),
[{domain_admin, Creds}, {schema_endpoint, domain_admin} | Config].

end_domain_admin_handler(Config) ->
{JID, _} = ?config(domain_admin, Config),
Domain = escalus_utils:get_server(JID),
domain_helper:delete_domain_password(mim(), Domain).

get_listener_opts(EpName) ->
#{handlers := Handlers} = get_listener_config(EpName),
[Opts2] = lists:filtermap(
Expand Down
18 changes: 18 additions & 0 deletions priv/graphql/schemas/admin/admin_auth_status.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"Inforamtion about user request authorization"
type AdminAuthInfo{
"Authorized for a domain"
domain: String
"Authorization status"
authStatus: AuthStatus!
"Authorization as a "
authType: AuthType
}

enum AuthType{
""
DOMAIN_ADMIN
""
ADMIN
""
UNAUTHORIZED
}
2 changes: 1 addition & 1 deletion priv/graphql/schemas/admin/admin_schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Only an authenticated admin can execute these queries.
"""
type AdminQuery{
"Check authorization status"
checkAuth: AuthStatus
checkAuth: AdminAuthInfo
"Domain management"
domains: DomainAdminQuery
"Account management"
Expand Down
2 changes: 1 addition & 1 deletion rel/fed1.vars-toml.config
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
port = {{ http_api_endpoint_port }}"}.
{http_api_client_endpoint, "port = {{ http_api_client_endpoint_port }}"}.
{http_graphql_api_admin_endpoint, "ip_address = \"127.0.0.1\"
port = {{http_qraphql_api_admin_endpoint_port}}"}.
port = {{http_graphql_api_admin_endpoint_port}}"}.
{http_graphql_api_domain_admin_endpoint, "ip_address = \"0.0.0.0\"
port = {{http_qraphql_api_domain_admin_endpoint_port}}"}.
{http_graphql_api_user_endpoint, "ip_address = \"0.0.0.0\"
Expand Down
2 changes: 1 addition & 1 deletion rel/mim2.vars-toml.config
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
{http_graphql_api_admin_endpoint, "ip_address = \"127.0.0.1\"
port = {{http_qraphql_api_admin_endpoint_port}}"}.
{http_graphql_api_domain_admin_endpoint, "ip_address = \"0.0.0.0\"
port = {{http_qraphql_api_domain_admin_endpoint_port}}"}.
port = {{http_graphql_api_domain_admin_endpoint_port}}"}.
{http_graphql_api_user_endpoint, "ip_address = \"0.0.0.0\"
port = {{http_graphql_api_user_endpoint_port}}"}.
{http_api_old_endpoint, "ip_address = \"127.0.0.1\"
Expand Down
2 changes: 1 addition & 1 deletion rel/mim3.vars-toml.config
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
{http_graphql_api_admin_endpoint, "ip_address = \"127.0.0.1\"
port = {{http_qraphql_api_admin_endpoint_port}}"}.
{http_graphql_api_domain_admin_endpoint, "ip_address = \"0.0.0.0\"
port = {{http_qraphql_api_domain_admin_endpoint_port}}"}.
port = {{http_graphql_api_domain_admin_endpoint_port}}"}.
{http_graphql_api_user_endpoint, "ip_address = \"0.0.0.0\"
port = {{http_graphql_api_user_endpoint_port}}"}.
{http_api_old_endpoint, "ip_address = \"127.0.0.1\"
Expand Down
2 changes: 1 addition & 1 deletion rel/reg1.vars-toml.config
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
{http_graphql_api_admin_endpoint, "ip_address = \"127.0.0.1\"
port = {{http_qraphql_api_admin_endpoint_port}}"}.
{http_graphql_api_domain_admin_endpoint, "ip_address = \"0.0.0.0\"
port = {{http_qraphql_api_domain_admin_endpoint_port}}"}.
port = {{http_graphql_api_domain_admin_endpoint_port}}"}.
{http_graphql_api_user_endpoint, "ip_address = \"0.0.0.0\"
port = {{http_graphql_api_user_endpoint_port}}"}.
{http_api_old_endpoint, "ip_address = \"127.0.0.1\"
Expand Down
2 changes: 1 addition & 1 deletion rel/vars-toml.config.in
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
{http_graphql_api_admin_endpoint, "ip_address = \"127.0.0.1\"
port = {{http_graphql_api_admin_endpoint_port}}"}.
{http_graphql_api_domain_admin_endpoint, "ip_address = \"0.0.0.0\"
port = {{http_qraphql_api_domain_admin_endpoint_port}}"}.
port = {{http_graphql_api_domain_admin_endpoint_port}}"}.
{http_graphql_api_user_endpoint, "ip_address = \"0.0.0.0\"
port = {{http_graphql_api_user_endpoint_port}}"}.
{http_api_endpoint, "ip_address = \"127.0.0.1\"
Expand Down
33 changes: 33 additions & 0 deletions src/domain/mongoose_domain_api.erl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
get_all_static/0,
get_domains_by_host_type/1]).

%% domain admin API
-export([check_domain_password/2,
set_domain_password/2,
delete_domain_password/1]).

%% subdomain API
-export([register_subdomain/3,
unregister_subdomain/2,
Expand Down Expand Up @@ -72,6 +77,7 @@ delete_domain(Domain, HostType) ->
Res = check_db(mongoose_domain_sql:delete_domain(Domain, HostType)),
case Res of
ok ->
delete_domain_password(Domain),
mongoose_hooks:remove_domain(HostType, Domain);
_ ->
ok
Expand Down Expand Up @@ -180,6 +186,33 @@ check_domain(Domain, HostType) ->
ok
end.

-type password() :: binary().

-spec check_domain_password(domain(), password()) -> ok | {error, wrong_password | not_found}.
check_domain_password(Domain, Password) ->
case mongoose_domain_sql:select_domain_admin(Domain) of
{ok, {Domain, Password}} ->
ok;
{ok, _} ->
{error, wrong_password};
{error, not_found} ->
{error, not_found}
end.

-spec set_domain_password(domain(), password()) -> ok | {error, not_found}.
set_domain_password(Domain, Password) ->
HostType = get_host_type(Domain),
case HostType of
{ok, _} ->
mongoose_domain_sql:set_domain_admin(Domain, Password);
{error, not_found} ->
{error, not_found}
end.

-spec delete_domain_password(domain()) -> ok.
delete_domain_password(Domain) ->
mongoose_domain_sql:delete_domain_admin(Domain).

-spec register_subdomain(host_type(), subdomain_pattern(),
mongoose_packet_handler:t()) ->
ok | {error, already_registered | subdomain_already_exists}.
Expand Down
19 changes: 9 additions & 10 deletions src/domain/mongoose_domain_sql.erl
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,15 @@ start(#{db_pool := Pool}) ->
%% Admins
prepare(domain_insert_admin, domain_admin, [domain, password],
<<"INSERT INTO domain_admin (domain, password) VALUES (?, ?)">>),
prepare(domain_update_admin_password, domain_admin, [password, domain],
prepare(domain_update_admin, domain_admin, [password, domain],
<<"UPDATE domain_admin"
"SET password = ? "
"WHERE domain = ?">>),
" SET password = ? "
" WHERE domain = ?">>),
prepare(domain_delete_admin, domain_admin, [domain],
<<"DELETE FROM domain_admin WHERE domain = ?">>),
prepare(domain_admin_select, domain_admin, [domain],
prepare(domain_select_admin, domain_admin, [domain],
<<"SELECT domain, password"
"FROM domain_admin WHERE domain = ?">>),
" FROM domain_admin WHERE domain = ?">>),
ok.

prepare_test_queries(Pool) ->
Expand Down Expand Up @@ -166,7 +166,7 @@ enable_domain(Domain) ->

select_domain_admin(Domain) ->
Pool = get_db_pool(),
case execute_successfully(Pool, domain_admin_select, [Domain]) of
case execute_successfully(Pool, domain_select_admin, [Domain]) of
{selected, []} ->
{error, not_found};
{selected, [Row]} ->
Expand Down Expand Up @@ -197,14 +197,13 @@ delete_domain_admin(Domain) ->
end).

insert_domain_admin(Pool, Domain, Password) ->
execute_successfully(Pool, insert_domain_admin, [Domain, Password]).
execute_successfully(Pool, domain_insert_admin, [Domain, Password]).

update_domain_admin(Pool, Domain, Password) ->
execute_successfully(Pool, update_domain_admin_password, [Domain, Password]).
execute_successfully(Pool, domain_update_admin, [Domain, Password]).

delete_domain_admin(Pool, Domain) ->
execute_successfully(Pool, delete_domain_admin, [Domain]).

execute_successfully(Pool, domain_delete_admin, [Domain]).

%% Returns smallest id first
select_from(FromId, Limit) ->
Expand Down
Loading

0 comments on commit 6127638

Please sign in to comment.