Merge pull request #6078 from savonarola/auth-api-schema-examples

refactor(authn api): add more schema examples
This commit is contained in:
Ilya Averyanov 2021-11-08 19:44:02 +03:00 committed by GitHub
commit 0f8ad29e91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 406 additions and 254 deletions

View File

@ -53,7 +53,14 @@
, listener_authenticator_user/2 , listener_authenticator_user/2
]). ]).
-export([authenticator_examples/0]). -export([ authenticator_examples/0
, request_move_examples/0
, request_import_users_examples/0
, request_user_create_examples/0
, request_user_update_examples/0
, response_user_examples/0
, response_users_example/0
]).
api_spec() -> api_spec() ->
emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}). emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
@ -78,13 +85,13 @@ roots() -> [ request_user_create
, request_move , request_move
, request_import_users , request_import_users
, response_user , response_user
, response_users
]. ].
fields(request_user_create) -> fields(request_user_create) ->
[ [
{user_id, binary()}, {user_id, binary()}
{password, binary()}, | fields(request_user_update)
{is_superuser, mk(boolean(), #{default => false, nullable => true})}
]; ];
fields(request_user_update) -> fields(request_user_update) ->
@ -103,11 +110,21 @@ fields(response_user) ->
[ [
{user_id, binary()}, {user_id, binary()},
{is_superuser, mk(boolean(), #{default => false, nullable => true})} {is_superuser, mk(boolean(), #{default => false, nullable => true})}
];
fields(response_users) ->
paginated_list_type(ref(response_user));
fields(pagination_meta) ->
[
{page, non_neg_integer()},
{limit, non_neg_integer()},
{count, non_neg_integer()}
]. ].
schema("/authentication") -> schema("/authentication") ->
#{ #{
operationId => authenticators, 'operationId' => authenticators,
get => #{ get => #{
tags => [<<"authentication">>, <<"global">>], tags => [<<"authentication">>, <<"global">>],
description => <<"List authenticators for global authentication">>, description => <<"List authenticators for global authentication">>,
@ -120,7 +137,7 @@ schema("/authentication") ->
post => #{ post => #{
tags => [<<"authentication">>, <<"global">>], tags => [<<"authentication">>, <<"global">>],
description => <<"Create authenticator for global authentication">>, description => <<"Create authenticator for global authentication">>,
requestBody => emqx_dashboard_swagger:schema_with_examples( 'requestBody' => emqx_dashboard_swagger:schema_with_examples(
emqx_authn_schema:authenticator_type(), emqx_authn_schema:authenticator_type(),
authenticator_examples()), authenticator_examples()),
responses => #{ responses => #{
@ -135,7 +152,7 @@ schema("/authentication") ->
schema("/authentication/:id") -> schema("/authentication/:id") ->
#{ #{
operationId => authenticator, 'operationId' => authenticator,
get => #{ get => #{
tags => [<<"authentication">>, <<"global">>], tags => [<<"authentication">>, <<"global">>],
description => <<"Get authenticator from global authentication chain">>, description => <<"Get authenticator from global authentication chain">>,
@ -151,7 +168,7 @@ schema("/authentication/:id") ->
tags => [<<"authentication">>, <<"global">>], tags => [<<"authentication">>, <<"global">>],
description => <<"Update authenticator from global authentication chain">>, description => <<"Update authenticator from global authentication chain">>,
parameters => [{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}], parameters => [{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}],
requestBody => emqx_dashboard_swagger:schema_with_examples( 'requestBody' => emqx_dashboard_swagger:schema_with_examples(
emqx_authn_schema:authenticator_type(), emqx_authn_schema:authenticator_type(),
authenticator_examples() authenticator_examples()
), ),
@ -177,7 +194,7 @@ schema("/authentication/:id") ->
schema("/listeners/:listener_id/authentication") -> schema("/listeners/:listener_id/authentication") ->
#{ #{
operationId => listener_authenticators, 'operationId' => listener_authenticators,
get => #{ get => #{
tags => [<<"authentication">>, <<"listener">>], tags => [<<"authentication">>, <<"listener">>],
description => <<"List authenticators for listener authentication">>, description => <<"List authenticators for listener authentication">>,
@ -192,7 +209,7 @@ schema("/listeners/:listener_id/authentication") ->
tags => [<<"authentication">>, <<"listener">>], tags => [<<"authentication">>, <<"listener">>],
description => <<"Create authenticator for listener authentication">>, description => <<"Create authenticator for listener authentication">>,
parameters => [{listener_id, mk(binary(), #{in => path, desc => <<"Listener ID">>})}], parameters => [{listener_id, mk(binary(), #{in => path, desc => <<"Listener ID">>})}],
requestBody => emqx_dashboard_swagger:schema_with_examples( 'requestBody' => emqx_dashboard_swagger:schema_with_examples(
emqx_authn_schema:authenticator_type(), emqx_authn_schema:authenticator_type(),
authenticator_examples() authenticator_examples()
), ),
@ -208,7 +225,7 @@ schema("/listeners/:listener_id/authentication") ->
schema("/listeners/:listener_id/authentication/:id") -> schema("/listeners/:listener_id/authentication/:id") ->
#{ #{
operationId => listener_authenticator, 'operationId' => listener_authenticator,
get => #{ get => #{
tags => [<<"authentication">>, <<"listener">>], tags => [<<"authentication">>, <<"listener">>],
description => <<"Get authenticator from listener authentication chain">>, description => <<"Get authenticator from listener authentication chain">>,
@ -230,7 +247,7 @@ schema("/listeners/:listener_id/authentication/:id") ->
{listener_id, mk(binary(), #{in => path, desc => <<"Listener ID">>})}, {listener_id, mk(binary(), #{in => path, desc => <<"Listener ID">>})},
{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})} {id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}
], ],
requestBody => emqx_dashboard_swagger:schema_with_examples( 'requestBody' => emqx_dashboard_swagger:schema_with_examples(
emqx_authn_schema:authenticator_type(), emqx_authn_schema:authenticator_type(),
authenticator_examples()), authenticator_examples()),
responses => #{ responses => #{
@ -259,12 +276,14 @@ schema("/listeners/:listener_id/authentication/:id") ->
schema("/authentication/:id/move") -> schema("/authentication/:id/move") ->
#{ #{
operationId => authenticator_move, 'operationId' => authenticator_move,
post => #{ post => #{
tags => [<<"authentication">>, <<"global">>], tags => [<<"authentication">>, <<"global">>],
description => <<"Move authenticator in global authentication chain">>, description => <<"Move authenticator in global authentication chain">>,
parameters => [{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}], parameters => [{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}],
requestBody => ref(request_move), 'requestBody' => emqx_dashboard_swagger:schema_with_examples(
ref(request_move),
request_move_examples()),
responses => #{ responses => #{
204 => <<"Authenticator moved">>, 204 => <<"Authenticator moved">>,
400 => error_codes([?BAD_REQUEST], <<"Bad Request">>), 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>),
@ -275,7 +294,7 @@ schema("/authentication/:id/move") ->
schema("/listeners/:listener_id/authentication/:id/move") -> schema("/listeners/:listener_id/authentication/:id/move") ->
#{ #{
operationId => listener_authenticator_move, 'operationId' => listener_authenticator_move,
post => #{ post => #{
tags => [<<"authentication">>, <<"listener">>], tags => [<<"authentication">>, <<"listener">>],
description => <<"Move authenticator in listener authentication chain">>, description => <<"Move authenticator in listener authentication chain">>,
@ -283,7 +302,9 @@ schema("/listeners/:listener_id/authentication/:id/move") ->
{listener_id, mk(binary(), #{in => path, desc => <<"Listener ID">>})}, {listener_id, mk(binary(), #{in => path, desc => <<"Listener ID">>})},
{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})} {id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}
], ],
requestBody => ref(request_move), 'requestBody' => emqx_dashboard_swagger:schema_with_examples(
ref(request_move),
request_move_examples()),
responses => #{ responses => #{
204 => <<"Authenticator moved">>, 204 => <<"Authenticator moved">>,
400 => error_codes([?BAD_REQUEST], <<"Bad Request">>), 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>),
@ -294,12 +315,14 @@ schema("/listeners/:listener_id/authentication/:id/move") ->
schema("/authentication/:id/import_users") -> schema("/authentication/:id/import_users") ->
#{ #{
operationId => authenticator_import_users, 'operationId' => authenticator_import_users,
post => #{ post => #{
tags => [<<"authentication">>, <<"global">>], tags => [<<"authentication">>, <<"global">>],
description => <<"Import users into authenticator in global authentication chain">>, description => <<"Import users into authenticator in global authentication chain">>,
parameters => [{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}], parameters => [{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}],
requestBody => ref(request_import_users), 'requestBody' => emqx_dashboard_swagger:schema_with_examples(
ref(request_import_users),
request_import_users_examples()),
responses => #{ responses => #{
204 => <<"Users imported">>, 204 => <<"Users imported">>,
400 => error_codes([?BAD_REQUEST], <<"Bad Request">>), 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>),
@ -310,7 +333,7 @@ schema("/authentication/:id/import_users") ->
schema("/listeners/:listener_id/authentication/:id/import_users") -> schema("/listeners/:listener_id/authentication/:id/import_users") ->
#{ #{
operationId => listener_authenticator_import_users, 'operationId' => listener_authenticator_import_users,
post => #{ post => #{
tags => [<<"authentication">>, <<"listener">>], tags => [<<"authentication">>, <<"listener">>],
description => <<"Import users into authenticator in listener authentication chain">>, description => <<"Import users into authenticator in listener authentication chain">>,
@ -318,7 +341,9 @@ schema("/listeners/:listener_id/authentication/:id/import_users") ->
{listener_id, mk(binary(), #{in => path, desc => <<"Listener ID">>})}, {listener_id, mk(binary(), #{in => path, desc => <<"Listener ID">>})},
{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})} {id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}
], ],
requestBody => ref(request_import_users), 'requestBody' => emqx_dashboard_swagger:schema_with_examples(
ref(request_import_users),
request_import_users_examples()),
responses => #{ responses => #{
204 => <<"Users imported">>, 204 => <<"Users imported">>,
400 => error_codes([?BAD_REQUEST], <<"Bad Request">>), 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>),
@ -329,14 +354,18 @@ schema("/listeners/:listener_id/authentication/:id/import_users") ->
schema("/authentication/:id/users") -> schema("/authentication/:id/users") ->
#{ #{
operationId => authenticator_users, 'operationId' => authenticator_users,
post => #{ post => #{
tags => [<<"authentication">>, <<"global">>], tags => [<<"authentication">>, <<"global">>],
description => <<"Create users for authenticator in global authentication chain">>, description => <<"Create users for authenticator in global authentication chain">>,
parameters => [{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}], parameters => [{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}],
requestBody => ref(request_user_create), 'requestBody' => emqx_dashboard_swagger:schema_with_examples(
ref(request_user_create),
request_user_create_examples()),
responses => #{ responses => #{
201 => ref(response_user), 201 => emqx_dashboard_swagger:schema_with_examples(
ref(response_user),
response_user_examples()),
400 => error_codes([?BAD_REQUEST], <<"Bad Request">>), 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>),
404 => error_codes([?NOT_FOUND], <<"Not Found">>) 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
} }
@ -350,7 +379,9 @@ schema("/authentication/:id/users") ->
{limit, mk(integer(), #{in => query, desc => <<"Page Limit">>, nullable => true})} {limit, mk(integer(), #{in => query, desc => <<"Page Limit">>, nullable => true})}
], ],
responses => #{ responses => #{
200 => mk(hoconsc:array(ref(response_user)), #{}), 200 => emqx_dashboard_swagger:schema_with_example(
ref(response_users),
response_users_example()),
404 => error_codes([?NOT_FOUND], <<"Not Found">>) 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
} }
@ -359,7 +390,7 @@ schema("/authentication/:id/users") ->
schema("/listeners/:listener_id/authentication/:id/users") -> schema("/listeners/:listener_id/authentication/:id/users") ->
#{ #{
operationId => listener_authenticator_users, 'operationId' => listener_authenticator_users,
post => #{ post => #{
tags => [<<"authentication">>, <<"listener">>], tags => [<<"authentication">>, <<"listener">>],
description => <<"Create users for authenticator in global authentication chain">>, description => <<"Create users for authenticator in global authentication chain">>,
@ -367,9 +398,13 @@ schema("/listeners/:listener_id/authentication/:id/users") ->
{listener_id, mk(binary(), #{in => path, desc => <<"Listener ID">>})}, {listener_id, mk(binary(), #{in => path, desc => <<"Listener ID">>})},
{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})} {id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}
], ],
requestBody => ref(request_user_create), 'requestBody' => emqx_dashboard_swagger:schema_with_examples(
ref(request_user_create),
request_user_create_examples()),
responses => #{ responses => #{
201 => ref(response_user), 201 => emqx_dashboard_swagger:schema_with_examples(
ref(response_user),
response_user_examples()),
400 => error_codes([?BAD_REQUEST], <<"Bad Request">>), 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>),
404 => error_codes([?NOT_FOUND], <<"Not Found">>) 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
} }
@ -384,7 +419,9 @@ schema("/listeners/:listener_id/authentication/:id/users") ->
{limit, mk(integer(), #{in => query, desc => <<"Page Limit">>, nullable => true})} {limit, mk(integer(), #{in => query, desc => <<"Page Limit">>, nullable => true})}
], ],
responses => #{ responses => #{
200 => mk(hoconsc:array(ref(response_user)), #{}), 200 => emqx_dashboard_swagger:schema_with_example(
ref(response_users),
response_users_example()),
404 => error_codes([?NOT_FOUND], <<"Not Found">>) 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
} }
@ -393,7 +430,7 @@ schema("/listeners/:listener_id/authentication/:id/users") ->
schema("/authentication/:id/users/:user_id") -> schema("/authentication/:id/users/:user_id") ->
#{ #{
operationId => authenticator_user, 'operationId' => authenticator_user,
get => #{ get => #{
tags => [<<"authentication">>, <<"global">>], tags => [<<"authentication">>, <<"global">>],
description => <<"Get user from authenticator in global authentication chain">>, description => <<"Get user from authenticator in global authentication chain">>,
@ -402,7 +439,9 @@ schema("/authentication/:id/users/:user_id") ->
{user_id, mk(binary(), #{in => path, desc => <<"User ID">>})} {user_id, mk(binary(), #{in => path, desc => <<"User ID">>})}
], ],
responses => #{ responses => #{
200 => ref(response_user), 200 => emqx_dashboard_swagger:schema_with_examples(
ref(response_user),
response_user_examples()),
404 => error_codes([?NOT_FOUND], <<"Not Found">>) 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
} }
}, },
@ -413,9 +452,13 @@ schema("/authentication/:id/users/:user_id") ->
{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}, {id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})},
{user_id, mk(binary(), #{in => path, desc => <<"User ID">>})} {user_id, mk(binary(), #{in => path, desc => <<"User ID">>})}
], ],
requestBody => ref(request_user_update), 'requestBody' => emqx_dashboard_swagger:schema_with_examples(
ref(request_user_update),
request_user_update_examples()),
responses => #{ responses => #{
200 => mk(hoconsc:array(ref(response_user)), #{}), 200 => emqx_dashboard_swagger:schema_with_example(
ref(response_user),
response_user_examples()),
400 => error_codes([?BAD_REQUEST], <<"Bad Request">>), 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>),
404 => error_codes([?NOT_FOUND], <<"Not Found">>) 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
} }
@ -436,7 +479,7 @@ schema("/authentication/:id/users/:user_id") ->
schema("/listeners/:listener_id/authentication/:id/users/:user_id") -> schema("/listeners/:listener_id/authentication/:id/users/:user_id") ->
#{ #{
operationId => listener_authenticator_user, 'operationId' => listener_authenticator_user,
get => #{ get => #{
tags => [<<"authentication">>, <<"listener">>], tags => [<<"authentication">>, <<"listener">>],
description => <<"Get user from authenticator in listener authentication chain">>, description => <<"Get user from authenticator in listener authentication chain">>,
@ -446,7 +489,9 @@ schema("/listeners/:listener_id/authentication/:id/users/:user_id") ->
{user_id, mk(binary(), #{in => path, desc => <<"User ID">>})} {user_id, mk(binary(), #{in => path, desc => <<"User ID">>})}
], ],
responses => #{ responses => #{
200 => ref(response_user), 200 => emqx_dashboard_swagger:schema_with_example(
ref(response_user),
response_user_examples()),
404 => error_codes([?NOT_FOUND], <<"Not Found">>) 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
} }
}, },
@ -458,9 +503,13 @@ schema("/listeners/:listener_id/authentication/:id/users/:user_id") ->
{id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})}, {id, mk(binary(), #{in => path, desc => <<"Authenticator ID">>})},
{user_id, mk(binary(), #{in => path, desc => <<"User ID">>})} {user_id, mk(binary(), #{in => path, desc => <<"User ID">>})}
], ],
requestBody => ref(request_user_update), 'requestBody' => emqx_dashboard_swagger:schema_with_example(
ref(request_user_update),
request_user_update_examples()),
responses => #{ responses => #{
200 => mk(hoconsc:array(ref(response_user)), #{}), 200 => emqx_dashboard_swagger:schema_with_example(
ref(response_user),
response_user_examples()),
400 => error_codes([?BAD_REQUEST], <<"Bad Request">>), 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>),
404 => error_codes([?NOT_FOUND], <<"Not Found">>) 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
} }
@ -516,7 +565,9 @@ listener_authenticator(get, #{bindings := #{listener_id := ListenerID, id := Aut
list_authenticator([listeners, Type, Name, authentication], list_authenticator([listeners, Type, Name, authentication],
AuthenticatorID) AuthenticatorID)
end); end);
listener_authenticator(put, #{bindings := #{listener_id := ListenerID, id := AuthenticatorID}, body := Config}) -> listener_authenticator(put,
#{bindings := #{listener_id := ListenerID, id := AuthenticatorID},
body := Config}) ->
with_listener(ListenerID, with_listener(ListenerID,
fun(Type, Name, ChainName) -> fun(Type, Name, ChainName) ->
update_authenticator([listeners, Type, Name, authentication], update_authenticator([listeners, Type, Name, authentication],
@ -524,7 +575,8 @@ listener_authenticator(put, #{bindings := #{listener_id := ListenerID, id := Aut
AuthenticatorID, AuthenticatorID,
Config) Config)
end); end);
listener_authenticator(delete, #{bindings := #{listener_id := ListenerID, id := AuthenticatorID}}) -> listener_authenticator(delete,
#{bindings := #{listener_id := ListenerID, id := AuthenticatorID}}) ->
with_listener(ListenerID, with_listener(ListenerID,
fun(Type, Name, ChainName) -> fun(Type, Name, ChainName) ->
delete_authenticator([listeners, Type, Name, authentication], delete_authenticator([listeners, Type, Name, authentication],
@ -532,12 +584,16 @@ listener_authenticator(delete, #{bindings := #{listener_id := ListenerID, id :=
AuthenticatorID) AuthenticatorID)
end). end).
authenticator_move(post, #{bindings := #{id := AuthenticatorID}, body := #{<<"position">> := Position}}) -> authenticator_move(post,
#{bindings := #{id := AuthenticatorID},
body := #{<<"position">> := Position}}) ->
move_authenitcator([authentication], ?GLOBAL, AuthenticatorID, Position); move_authenitcator([authentication], ?GLOBAL, AuthenticatorID, Position);
authenticator_move(post, #{bindings := #{id := _}, body := _}) -> authenticator_move(post, #{bindings := #{id := _}, body := _}) ->
serialize_error({missing_parameter, position}). serialize_error({missing_parameter, position}).
listener_authenticator_move(post, #{bindings := #{listener_id := ListenerID, id := AuthenticatorID}, body := #{<<"position">> := Position}}) -> listener_authenticator_move(post,
#{bindings := #{listener_id := ListenerID, id := AuthenticatorID},
body := #{<<"position">> := Position}}) ->
with_listener(ListenerID, with_listener(ListenerID,
fun(Type, Name, ChainName) -> fun(Type, Name, ChainName) ->
move_authenitcator([listeners, Type, Name, authentication], move_authenitcator([listeners, Type, Name, authentication],
@ -548,22 +604,28 @@ listener_authenticator_move(post, #{bindings := #{listener_id := ListenerID, id
listener_authenticator_move(post, #{bindings := #{listener_id := _, id := _}, body := _}) -> listener_authenticator_move(post, #{bindings := #{listener_id := _, id := _}, body := _}) ->
serialize_error({missing_parameter, position}). serialize_error({missing_parameter, position}).
authenticator_import_users(post, #{bindings := #{id := AuthenticatorID}, body := #{<<"filename">> := Filename}}) -> authenticator_import_users(post,
case ?AUTHN:import_users(?GLOBAL, AuthenticatorID, Filename) of #{bindings := #{id := AuthenticatorID},
body := #{<<"filename">> := Filename}}) ->
case emqx_authentication:import_users(?GLOBAL, AuthenticatorID, Filename) of
ok -> {204}; ok -> {204};
{error, Reason} -> serialize_error(Reason) {error, Reason} -> serialize_error(Reason)
end; end;
authenticator_import_users(post, #{bindings := #{id := _}, body := _}) -> authenticator_import_users(post, #{bindings := #{id := _}, body := _}) ->
serialize_error({missing_parameter, filename}). serialize_error({missing_parameter, filename}).
listener_authenticator_import_users(post, #{bindings := #{listener_id := ListenerID, id := AuthenticatorID}, body := #{<<"filename">> := Filename}}) -> listener_authenticator_import_users(
with_chain(ListenerID, post,
fun(ChainName) -> #{bindings := #{listener_id := ListenerID, id := AuthenticatorID},
case ?AUTHN:import_users(ChainName, AuthenticatorID, Filename) of body := #{<<"filename">> := Filename}}) ->
ok -> {204}; with_chain(
{error, Reason} -> serialize_error(Reason) ListenerID,
end fun(ChainName) ->
end); case emqx_authentication:import_users(ChainName, AuthenticatorID, Filename) of
ok -> {204};
{error, Reason} -> serialize_error(Reason)
end
end);
listener_authenticator_import_users(post, #{bindings := #{listener_id := _, id := _}, body := _}) -> listener_authenticator_import_users(post, #{bindings := #{listener_id := _, id := _}, body := _}) ->
serialize_error({missing_parameter, filename}). serialize_error({missing_parameter, filename}).
@ -644,7 +706,7 @@ find_listener(ListenerID) ->
end. end.
with_chain(ListenerID, Fun) -> with_chain(ListenerID, Fun) ->
{ok, ChainNames} = ?AUTHN:list_chain_names(), {ok, ChainNames} = emqx_authentication:list_chain_names(),
ListenerChainName = ListenerChainName =
[ Name || Name <- ChainNames, atom_to_binary(Name) =:= ListenerID ], [ Name || Name <- ChainNames, atom_to_binary(Name) =:= ListenerID ],
case ListenerChainName of case ListenerChainName of
@ -656,7 +718,7 @@ with_chain(ListenerID, Fun) ->
create_authenticator(ConfKeyPath, ChainName, Config) -> create_authenticator(ConfKeyPath, ChainName, Config) ->
case update_config(ConfKeyPath, {create_authenticator, ChainName, Config}) of case update_config(ConfKeyPath, {create_authenticator, ChainName, Config}) of
{ok, #{post_config_update := #{?AUTHN := #{id := ID}}, {ok, #{post_config_update := #{emqx_authentication := #{id := ID}},
raw_config := AuthenticatorsConfig}} -> raw_config := AuthenticatorsConfig}} ->
{ok, AuthenticatorConfig} = find_config(ID, AuthenticatorsConfig), {ok, AuthenticatorConfig} = find_config(ID, AuthenticatorsConfig),
{200, maps:put(id, ID, convert_certs(fill_defaults(AuthenticatorConfig)))}; {200, maps:put(id, ID, convert_certs(fill_defaults(AuthenticatorConfig)))};
@ -666,7 +728,10 @@ create_authenticator(ConfKeyPath, ChainName, Config) ->
list_authenticators(ConfKeyPath) -> list_authenticators(ConfKeyPath) ->
AuthenticatorsConfig = get_raw_config_with_defaults(ConfKeyPath), AuthenticatorsConfig = get_raw_config_with_defaults(ConfKeyPath),
NAuthenticators = [maps:put(id, ?AUTHN:authenticator_id(AuthenticatorConfig), convert_certs(AuthenticatorConfig)) NAuthenticators = [ maps:put(
id,
emqx_authentication:authenticator_id(AuthenticatorConfig),
convert_certs(AuthenticatorConfig))
|| AuthenticatorConfig <- AuthenticatorsConfig], || AuthenticatorConfig <- AuthenticatorsConfig],
{200, NAuthenticators}. {200, NAuthenticators}.
@ -681,7 +746,7 @@ list_authenticator(ConfKeyPath, AuthenticatorID) ->
update_authenticator(ConfKeyPath, ChainName, AuthenticatorID, Config) -> update_authenticator(ConfKeyPath, ChainName, AuthenticatorID, Config) ->
case update_config(ConfKeyPath, {update_authenticator, ChainName, AuthenticatorID, Config}) of case update_config(ConfKeyPath, {update_authenticator, ChainName, AuthenticatorID, Config}) of
{ok, #{post_config_update := #{?AUTHN := #{id := ID}}, {ok, #{post_config_update := #{emqx_authentication := #{id := ID}},
raw_config := AuthenticatorsConfig}} -> raw_config := AuthenticatorsConfig}} ->
{ok, AuthenticatorConfig} = find_config(ID, AuthenticatorsConfig), {ok, AuthenticatorConfig} = find_config(ID, AuthenticatorsConfig),
{200, maps:put(id, ID, convert_certs(fill_defaults(AuthenticatorConfig)))}; {200, maps:put(id, ID, convert_certs(fill_defaults(AuthenticatorConfig)))};
@ -700,7 +765,9 @@ delete_authenticator(ConfKeyPath, ChainName, AuthenticatorID) ->
move_authenitcator(ConfKeyPath, ChainName, AuthenticatorID, Position) -> move_authenitcator(ConfKeyPath, ChainName, AuthenticatorID, Position) ->
case parse_position(Position) of case parse_position(Position) of
{ok, NPosition} -> {ok, NPosition} ->
case update_config(ConfKeyPath, {move_authenticator, ChainName, AuthenticatorID, NPosition}) of case update_config(
ConfKeyPath,
{move_authenticator, ChainName, AuthenticatorID, NPosition}) of
{ok, _} -> {ok, _} ->
{204}; {204};
{error, {_, _, Reason}} -> {error, {_, _, Reason}} ->
@ -710,9 +777,11 @@ move_authenitcator(ConfKeyPath, ChainName, AuthenticatorID, Position) ->
serialize_error(Reason) serialize_error(Reason)
end. end.
add_user(ChainName, AuthenticatorID, #{<<"user_id">> := UserID, <<"password">> := Password} = UserInfo) -> add_user(ChainName,
AuthenticatorID,
#{<<"user_id">> := UserID, <<"password">> := Password} = UserInfo) ->
IsSuperuser = maps:get(<<"is_superuser">>, UserInfo, false), IsSuperuser = maps:get(<<"is_superuser">>, UserInfo, false),
case ?AUTHN:add_user(ChainName, AuthenticatorID, #{ user_id => UserID case emqx_authentication:add_user(ChainName, AuthenticatorID, #{ user_id => UserID
, password => Password , password => Password
, is_superuser => IsSuperuser}) of , is_superuser => IsSuperuser}) of
{ok, User} -> {ok, User} ->
@ -730,7 +799,7 @@ update_user(ChainName, AuthenticatorID, UserID, UserInfo) ->
true -> true ->
serialize_error({missing_parameter, password}); serialize_error({missing_parameter, password});
false -> false ->
case ?AUTHN:update_user(ChainName, AuthenticatorID, UserID, UserInfo) of case emqx_authentication:update_user(ChainName, AuthenticatorID, UserID, UserInfo) of
{ok, User} -> {ok, User} ->
{200, User}; {200, User};
{error, Reason} -> {error, Reason} ->
@ -739,7 +808,7 @@ update_user(ChainName, AuthenticatorID, UserID, UserInfo) ->
end. end.
find_user(ChainName, AuthenticatorID, UserID) -> find_user(ChainName, AuthenticatorID, UserID) ->
case ?AUTHN:lookup_user(ChainName, AuthenticatorID, UserID) of case emqx_authentication:lookup_user(ChainName, AuthenticatorID, UserID) of
{ok, User} -> {ok, User} ->
{200, User}; {200, User};
{error, Reason} -> {error, Reason} ->
@ -747,7 +816,7 @@ find_user(ChainName, AuthenticatorID, UserID) ->
end. end.
delete_user(ChainName, AuthenticatorID, UserID) -> delete_user(ChainName, AuthenticatorID, UserID) ->
case ?AUTHN:delete_user(ChainName, AuthenticatorID, UserID) of case emqx_authentication:delete_user(ChainName, AuthenticatorID, UserID) of
ok -> ok ->
{204}; {204};
{error, Reason} -> {error, Reason} ->
@ -755,7 +824,7 @@ delete_user(ChainName, AuthenticatorID, UserID) ->
end. end.
list_users(ChainName, AuthenticatorID, PageParams) -> list_users(ChainName, AuthenticatorID, PageParams) ->
case ?AUTHN:list_users(ChainName, AuthenticatorID, PageParams) of case emqx_authentication:list_users(ChainName, AuthenticatorID, PageParams) of
{ok, Users} -> {ok, Users} ->
{200, Users}; {200, Users};
{error, Reason} -> {error, Reason} ->
@ -771,7 +840,11 @@ get_raw_config_with_defaults(ConfKeyPath) ->
ensure_list(fill_defaults(RawConfig)). ensure_list(fill_defaults(RawConfig)).
find_config(AuthenticatorID, AuthenticatorsConfig) -> find_config(AuthenticatorID, AuthenticatorsConfig) ->
case [AC || AC <- ensure_list(AuthenticatorsConfig), AuthenticatorID =:= ?AUTHN:authenticator_id(AC)] of MatchingACs
= [AC
|| AC <- ensure_list(AuthenticatorsConfig),
AuthenticatorID =:= emqx_authentication:authenticator_id(AC)],
case MatchingACs of
[] -> {error, {not_found, {authenticator, AuthenticatorID}}}; [] -> {error, {not_found, {authenticator, AuthenticatorID}}};
[AuthenticatorConfig] -> {ok, AuthenticatorConfig} [AuthenticatorConfig] -> {ok, AuthenticatorConfig}
end. end.
@ -860,6 +933,12 @@ ensure_list(L) when is_list(L) -> L.
binfmt(Fmt, Args) -> iolist_to_binary(io_lib:format(Fmt, Args)). binfmt(Fmt, Args) -> iolist_to_binary(io_lib:format(Fmt, Args)).
paginated_list_type(Type) ->
[
{data, hoconsc:array(Type)},
{meta, ref(pagination_meta)}
].
authenticator_array_example() -> authenticator_array_example() ->
[Config || #{value := Config} <- maps:values(authenticator_examples())]. [Config || #{value := Config} <- maps:values(authenticator_examples())].
@ -941,3 +1020,112 @@ authenticator_examples() ->
} }
} }
}. }.
request_user_create_examples() ->
#{
regular_user => #{
summary => <<"Regular user">>,
value => #{
user_id => <<"user1">>,
password => <<"secret">>
}
},
super_user => #{
summary => <<"Superuser">>,
value => #{
user_id => <<"user2">>,
password => <<"secret">>,
is_superuser => true
}
}
}.
request_user_update_examples() ->
#{
regular_user => #{
summary => <<"Update regular user">>,
value => #{
password => <<"newsecret">>
}
},
super_user => #{
summary => <<"Update user and promote to superuser">>,
value => #{
password => <<"newsecret">>,
is_superuser => true
}
}
}.
request_move_examples() ->
#{
move_to_top => #{
summary => <<"Move authenticator to the beginning of the chain">>,
value => #{
position => <<"top">>
}
},
move_to_bottom => #{
summary => <<"Move authenticator to the end of the chain">>,
value => #{
position => <<"bottom">>
}
},
'move_before_password-based:built-in-database' => #{
summary => <<"Move authenticator to the position preceding some other authenticator">>,
value => #{
position => <<"before:password-based:built-in-database">>
}
}
}.
request_import_users_examples() ->
#{
import_csv => #{
summary => <<"Import users from CSV file">>,
value => #{
filename => <<"/path/to/user/data.csv">>
}
},
import_json => #{
summary => <<"Import users from JSON file">>,
value => #{
filename => <<"/path/to/user/data.json">>
}
}
}.
response_user_examples() ->
#{
regular_user => #{
summary => <<"Regular user">>,
value => #{
user_id => <<"user1">>
}
},
super_user => #{
summary => <<"Superuser">>,
value => #{
user_id => <<"user2">>,
is_superuser => true
}
}
}.
response_users_example() ->
#{
data => [
#{
user_id => <<"user1">>
},
#{
user_id => <<"user2">>,
is_superuser => true
}
],
meta => #{
page => 0,
limit => 20,
count => 300
}
}.

View File

@ -49,7 +49,9 @@ init_per_testcase(_, Config) ->
Config. Config.
init_per_suite(Config) -> init_per_suite(Config) ->
ok = emqx_common_test_helpers:start_apps([emqx_authn, emqx_dashboard], fun set_special_configs/1), ok = emqx_common_test_helpers:start_apps(
[emqx_authn, emqx_dashboard],
fun set_special_configs/1),
Config. Config.
end_per_suite(_Config) -> end_per_suite(_Config) ->
@ -118,309 +120,275 @@ test_authenticators(PathPrefix) ->
ValidConfig = emqx_authn_test_lib:http_example(), ValidConfig = emqx_authn_test_lib:http_example(),
{ok, 200, _} = request( {ok, 200, _} = request(
post, post,
uri(PathPrefix ++ ["authentication"]), uri(PathPrefix ++ ["authentication"]),
ValidConfig), ValidConfig),
InvalidConfig = ValidConfig#{method => <<"delete">>}, InvalidConfig = ValidConfig#{method => <<"delete">>},
{ok, 400, _} = request( {ok, 400, _} = request(
post, post,
uri(PathPrefix ++ ["authentication"]), uri(PathPrefix ++ ["authentication"]),
InvalidConfig), InvalidConfig),
?assertAuthenticatorsMatch( ?assertAuthenticatorsMatch(
[#{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"http">>}], [#{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"http">>}],
PathPrefix ++ ["authentication"]). PathPrefix ++ ["authentication"]).
test_authenticator(PathPrefix) -> test_authenticator(PathPrefix) ->
ValidConfig0 = emqx_authn_test_lib:http_example(), ValidConfig0 = emqx_authn_test_lib:http_example(),
{ok, 200, _} = request( {ok, 200, _} = request(
post, post,
uri(PathPrefix ++ ["authentication"]), uri(PathPrefix ++ ["authentication"]),
ValidConfig0), ValidConfig0),
{ok, 200, _} = request( {ok, 200, _} = request(
get, get,
uri(PathPrefix ++ ["authentication", "password-based:http"])), uri(PathPrefix ++ ["authentication", "password-based:http"])),
{ok, 404, _} = request( {ok, 404, _} = request(
get, get,
uri(PathPrefix ++ ["authentication", "password-based:redis"])), uri(PathPrefix ++ ["authentication", "password-based:redis"])),
{ok, 404, _} = request( {ok, 404, _} = request(
put, put,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database"]), uri(PathPrefix ++ ["authentication", "password-based:built-in-database"]),
emqx_authn_test_lib:built_in_database_example()), emqx_authn_test_lib:built_in_database_example()),
InvalidConfig0 = ValidConfig0#{method => <<"delete">>}, InvalidConfig0 = ValidConfig0#{method => <<"delete">>},
{ok, 400, _} = request( {ok, 400, _} = request(
put, put,
uri(PathPrefix ++ ["authentication", "password-based:http"]), uri(PathPrefix ++ ["authentication", "password-based:http"]),
InvalidConfig0), InvalidConfig0),
ValidConfig1 = ValidConfig0#{pool_size => 9}, ValidConfig1 = ValidConfig0#{pool_size => 9},
{ok, 200, _} = request( {ok, 200, _} = request(
put, put,
uri(PathPrefix ++ ["authentication", "password-based:http"]), uri(PathPrefix ++ ["authentication", "password-based:http"]),
ValidConfig1), ValidConfig1),
{ok, 404, _} = request( {ok, 404, _} = request(
delete, delete,
uri(PathPrefix ++ ["authentication", "password-based:redis"])), uri(PathPrefix ++ ["authentication", "password-based:redis"])),
{ok, 204, _} = request( {ok, 204, _} = request(
delete, delete,
uri(PathPrefix ++ ["authentication", "password-based:http"])), uri(PathPrefix ++ ["authentication", "password-based:http"])),
?assertAuthenticatorsMatch([], PathPrefix ++ ["authentication"]). ?assertAuthenticatorsMatch([], PathPrefix ++ ["authentication"]).
test_authenticator_users(PathPrefix) -> test_authenticator_users(PathPrefix) ->
UsersUri = uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users"]),
{ok, 200, _} = request( {ok, 200, _} = request(
post, post,
uri(PathPrefix ++ ["authentication"]), uri(PathPrefix ++ ["authentication"]),
emqx_authn_test_lib:built_in_database_example()), emqx_authn_test_lib:built_in_database_example()),
InvalidUsers = [ InvalidUsers = [
#{clientid => <<"u1">>, password => <<"p1">>}, #{clientid => <<"u1">>, password => <<"p1">>},
#{user_id => <<"u2">>}, #{user_id => <<"u2">>},
#{user_id => <<"u3">>, password => <<"p3">>, foobar => <<"foobar">>}], #{user_id => <<"u3">>, password => <<"p3">>, foobar => <<"foobar">>}],
lists:foreach( lists:foreach(
fun(User) -> fun(User) -> {ok, 400, _} = request(post, UsersUri, User) end,
{ok, 400, _} = request( InvalidUsers),
post,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users"]),
User)
end,
InvalidUsers),
ValidUsers = [ ValidUsers = [
#{user_id => <<"u1">>, password => <<"p1">>}, #{user_id => <<"u1">>, password => <<"p1">>},
#{user_id => <<"u2">>, password => <<"p2">>, is_superuser => true}, #{user_id => <<"u2">>, password => <<"p2">>, is_superuser => true},
#{user_id => <<"u3">>, password => <<"p3">>}], #{user_id => <<"u3">>, password => <<"p3">>}],
lists:foreach( lists:foreach(
fun(User) -> fun(User) ->
{ok, 201, _} = request( {ok, 201, UserData} = request(post, UsersUri, User),
post, CreatedUser = jiffy:decode(UserData, [return_maps]),
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users"]), ?assertMatch(#{<<"user_id">> := _}, CreatedUser)
User) end,
end, ValidUsers),
ValidUsers),
{ok, 200, Page1Data} = {ok, 200, Page1Data} = request(get, UsersUri ++ "?page=1&limit=2"),
request(
get,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users"]) ++ "?page=1&limit=2"),
Page1Users = response_data(Page1Data), #{<<"data">> := Page1Users,
<<"meta">> :=
#{<<"page">> := 1,
<<"limit">> := 2,
<<"count">> := 3}} =
jiffy:decode(Page1Data, [return_maps]),
{ok, 200, Page2Data} = {ok, 200, Page2Data} = request(get, UsersUri ++ "?page=2&limit=2"),
request(
get,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users"]) ++ "?page=2&limit=2"),
Page2Users = response_data(Page2Data), #{<<"data">> := Page2Users,
<<"meta">> :=
#{<<"page">> := 2,
<<"limit">> := 2,
<<"count">> := 3}} = jiffy:decode(Page2Data, [return_maps]),
?assertEqual(2, length(Page1Users)), ?assertEqual(2, length(Page1Users)),
?assertEqual(1, length(Page2Users)), ?assertEqual(1, length(Page2Users)),
?assertEqual( ?assertEqual(
[<<"u1">>, <<"u2">>, <<"u3">>], [<<"u1">>, <<"u2">>, <<"u3">>],
lists:usort([ UserId || #{<<"user_id">> := UserId} <- Page1Users ++ Page2Users])). lists:usort([ UserId || #{<<"user_id">> := UserId} <- Page1Users ++ Page2Users])).
test_authenticator_user(PathPrefix) -> test_authenticator_user(PathPrefix) ->
UsersUri = uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users"]),
{ok, 200, _} = request( {ok, 200, _} = request(
post, post,
uri(PathPrefix ++ ["authentication"]), uri(PathPrefix ++ ["authentication"]),
emqx_authn_test_lib:built_in_database_example()), emqx_authn_test_lib:built_in_database_example()),
User = #{user_id => <<"u1">>, password => <<"p1">>}, User = #{user_id => <<"u1">>, password => <<"p1">>},
{ok, 201, _} = request( {ok, 201, _} = request(post, UsersUri, User),
post,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users"]),
User),
{ok, 404, _} = request( {ok, 404, _} = request(get, UsersUri ++ "/u123"),
get,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users", "u123"])),
{ok, 409, _} = request( {ok, 409, _} = request(post, UsersUri, User),
post,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users"]),
User),
{ok, 200, UserData} = request( {ok, 200, UserData} = request(get, UsersUri ++ "/u1"),
get,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users", "u1"])),
FetchedUser = jiffy:decode(UserData, [return_maps]), FetchedUser = jiffy:decode(UserData, [return_maps]),
?assertMatch(#{<<"user_id">> := <<"u1">>}, FetchedUser), ?assertMatch(#{<<"user_id">> := <<"u1">>}, FetchedUser),
?assertNotMatch(#{<<"password">> := _}, FetchedUser), ?assertNotMatch(#{<<"password">> := _}, FetchedUser),
ValidUserUpdates = [ ValidUserUpdates = [
#{password => <<"p1">>}, #{password => <<"p1">>},
#{password => <<"p1">>, is_superuser => true}], #{password => <<"p1">>, is_superuser => true}],
lists:foreach( lists:foreach(
fun(UserUpdate) -> fun(UserUpdate) -> {ok, 200, _} = request(put, UsersUri ++ "/u1", UserUpdate) end,
{ok, 200, _} = request( ValidUserUpdates),
put,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users", "u1"]),
UserUpdate)
end,
ValidUserUpdates),
InvalidUserUpdates = [ InvalidUserUpdates = [
#{user_id => <<"u1">>, password => <<"p1">>}, #{user_id => <<"u1">>, password => <<"p1">>},
#{is_superuser => true}], #{is_superuser => true}],
lists:foreach( lists:foreach(
fun(UserUpdate) -> fun(UserUpdate) -> {ok, 400, _} = request(put, UsersUri ++ "/u1", UserUpdate) end,
{ok, 400, _} = request( InvalidUserUpdates),
put,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users", "u1"]),
UserUpdate)
end,
InvalidUserUpdates),
{ok, 404, _} = request( {ok, 404, _} = request(delete, UsersUri ++ "/u123"),
delete, {ok, 204, _} = request(delete, UsersUri ++ "/u1").
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users", "u123"])),
{ok, 204, _} = request(
delete,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users", "u1"])).
test_authenticator_move(PathPrefix) -> test_authenticator_move(PathPrefix) ->
AuthenticatorConfs = [ AuthenticatorConfs = [
emqx_authn_test_lib:http_example(), emqx_authn_test_lib:http_example(),
emqx_authn_test_lib:jwt_example(), emqx_authn_test_lib:jwt_example(),
emqx_authn_test_lib:built_in_database_example() emqx_authn_test_lib:built_in_database_example()
], ],
lists:foreach( lists:foreach(
fun(Conf) -> fun(Conf) ->
{ok, 200, _} = request( {ok, 200, _} = request(
post, post,
uri(PathPrefix ++ ["authentication"]), uri(PathPrefix ++ ["authentication"]),
Conf) Conf)
end, end,
AuthenticatorConfs), AuthenticatorConfs),
?assertAuthenticatorsMatch( ?assertAuthenticatorsMatch(
[ [
#{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"http">>}, #{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"http">>},
#{<<"mechanism">> := <<"jwt">>}, #{<<"mechanism">> := <<"jwt">>},
#{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"built-in-database">>} #{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"built-in-database">>}
], ],
PathPrefix ++ ["authentication"]), PathPrefix ++ ["authentication"]),
% Invalid moves % Invalid moves
{ok, 400, _} = request( {ok, 400, _} = request(
post, post,
uri(PathPrefix ++ ["authentication", "jwt", "move"]), uri(PathPrefix ++ ["authentication", "jwt", "move"]),
#{position => <<"up">>}), #{position => <<"up">>}),
{ok, 400, _} = request( {ok, 400, _} = request(
post, post,
uri(PathPrefix ++ ["authentication", "jwt", "move"]), uri(PathPrefix ++ ["authentication", "jwt", "move"]),
#{}), #{}),
{ok, 404, _} = request( {ok, 404, _} = request(
post, post,
uri(PathPrefix ++ ["authentication", "jwt", "move"]), uri(PathPrefix ++ ["authentication", "jwt", "move"]),
#{position => <<"before:invalid">>}), #{position => <<"before:invalid">>}),
{ok, 404, _} = request( {ok, 404, _} = request(
post, post,
uri(PathPrefix ++ ["authentication", "jwt", "move"]), uri(PathPrefix ++ ["authentication", "jwt", "move"]),
#{position => <<"before:password-based:redis">>}), #{position => <<"before:password-based:redis">>}),
{ok, 404, _} = request( {ok, 404, _} = request(
post, post,
uri(PathPrefix ++ ["authentication", "jwt", "move"]), uri(PathPrefix ++ ["authentication", "jwt", "move"]),
#{position => <<"before:password-based:redis">>}), #{position => <<"before:password-based:redis">>}),
% Valid moves % Valid moves
{ok, 204, _} = request( {ok, 204, _} = request(
post, post,
uri(PathPrefix ++ ["authentication", "jwt", "move"]), uri(PathPrefix ++ ["authentication", "jwt", "move"]),
#{position => <<"top">>}), #{position => <<"top">>}),
?assertAuthenticatorsMatch( ?assertAuthenticatorsMatch(
[ [
#{<<"mechanism">> := <<"jwt">>}, #{<<"mechanism">> := <<"jwt">>},
#{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"http">>}, #{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"http">>},
#{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"built-in-database">>} #{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"built-in-database">>}
], ],
PathPrefix ++ ["authentication"]), PathPrefix ++ ["authentication"]),
{ok, 204, _} = request( {ok, 204, _} = request(
post, post,
uri(PathPrefix ++ ["authentication", "jwt", "move"]), uri(PathPrefix ++ ["authentication", "jwt", "move"]),
#{position => <<"bottom">>}), #{position => <<"bottom">>}),
?assertAuthenticatorsMatch( ?assertAuthenticatorsMatch(
[ [
#{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"http">>}, #{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"http">>},
#{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"built-in-database">>}, #{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"built-in-database">>},
#{<<"mechanism">> := <<"jwt">>} #{<<"mechanism">> := <<"jwt">>}
], ],
PathPrefix ++ ["authentication"]), PathPrefix ++ ["authentication"]),
{ok, 204, _} = request( {ok, 204, _} = request(
post, post,
uri(PathPrefix ++ ["authentication", "jwt", "move"]), uri(PathPrefix ++ ["authentication", "jwt", "move"]),
#{position => <<"before:password-based:built-in-database">>}), #{position => <<"before:password-based:built-in-database">>}),
?assertAuthenticatorsMatch( ?assertAuthenticatorsMatch(
[ [
#{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"http">>}, #{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"http">>},
#{<<"mechanism">> := <<"jwt">>}, #{<<"mechanism">> := <<"jwt">>},
#{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"built-in-database">>} #{<<"mechanism">> := <<"password-based">>, <<"backend">> := <<"built-in-database">>}
], ],
PathPrefix ++ ["authentication"]). PathPrefix ++ ["authentication"]).
test_authenticator_import_users(PathPrefix) -> test_authenticator_import_users(PathPrefix) ->
ImportUri = uri(
PathPrefix ++
["authentication", "password-based:built-in-database", "import_users"]),
{ok, 200, _} = request( {ok, 200, _} = request(
post, post,
uri(PathPrefix ++ ["authentication"]), uri(PathPrefix ++ ["authentication"]),
emqx_authn_test_lib:built_in_database_example()), emqx_authn_test_lib:built_in_database_example()),
{ok, 400, _} = request( {ok, 400, _} = request(post, ImportUri, #{}),
post,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "import_users"]),
#{}),
{ok, 400, _} = request( {ok, 400, _} = request(post, ImportUri, #{filename => <<"/etc/passwd">>}),
post,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "import_users"]),
#{filename => <<"/etc/passwd">>}),
{ok, 400, _} = request( {ok, 400, _} = request(post, ImportUri, #{filename => <<"/not_exists.csv">>}),
post,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "import_users"]),
#{filename => <<"/not_exists.csv">>}),
Dir = code:lib_dir(emqx_authn, test), Dir = code:lib_dir(emqx_authn, test),
JSONFileName = filename:join([Dir, <<"data/user-credentials.json">>]), JSONFileName = filename:join([Dir, <<"data/user-credentials.json">>]),
CSVFileName = filename:join([Dir, <<"data/user-credentials.csv">>]), CSVFileName = filename:join([Dir, <<"data/user-credentials.csv">>]),
{ok, 204, _} = request( {ok, 204, _} = request(post, ImportUri, #{filename => JSONFileName}),
post,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "import_users"]),
#{filename => JSONFileName}),
{ok, 204, _} = request( {ok, 204, _} = request(post, ImportUri, #{filename => CSVFileName}).
post,
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "import_users"]),
#{filename => CSVFileName}).
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------
%% Helpers %% Helpers
@ -440,10 +408,6 @@ delete_authenticators(Path, Chain) ->
Authenticators) Authenticators)
end. end.
response_data(Response) ->
#{<<"data">> := Data} = jiffy:decode(Response, [return_maps]),
Data.
request(Method, Url) -> request(Method, Url) ->
request(Method, Url, []). request(Method, Url, []).