refactor(authn api): add more schema examples
This commit is contained in:
parent
74e28cc4e9
commit
1e036bf74d
|
@ -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,6 +85,7 @@ 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) ->
|
||||||
|
@ -103,6 +111,16 @@ 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") ->
|
||||||
|
@ -264,7 +282,9 @@ schema("/authentication/:id/move") ->
|
||||||
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">>),
|
||||||
|
@ -283,7 +303,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">>),
|
||||||
|
@ -299,7 +321,9 @@ schema("/authentication/:id/import_users") ->
|
||||||
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">>),
|
||||||
|
@ -318,7 +342,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">>),
|
||||||
|
@ -334,9 +360,13 @@ schema("/authentication/:id/users") ->
|
||||||
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 +380,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">>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,9 +399,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 +420,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">>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +440,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 +453,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">>)
|
||||||
}
|
}
|
||||||
|
@ -446,7 +490,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 +504,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">>)
|
||||||
}
|
}
|
||||||
|
@ -860,6 +910,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 +997,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
|
||||||
|
}
|
||||||
|
}.
|
||||||
|
|
|
@ -204,10 +204,13 @@ test_authenticator_users(PathPrefix) ->
|
||||||
|
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(User) ->
|
fun(User) ->
|
||||||
{ok, 201, _} = request(
|
{ok, 201, UserData} = request(
|
||||||
post,
|
post,
|
||||||
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users"]),
|
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users"]),
|
||||||
User)
|
User),
|
||||||
|
CreatedUser = jiffy:decode(UserData, [return_maps]),
|
||||||
|
?assertMatch(#{<<"user_id">> := _}, CreatedUser)
|
||||||
|
|
||||||
end,
|
end,
|
||||||
ValidUsers),
|
ValidUsers),
|
||||||
|
|
||||||
|
@ -216,14 +219,24 @@ test_authenticator_users(PathPrefix) ->
|
||||||
get,
|
get,
|
||||||
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users"]) ++ "?page=1&limit=2"),
|
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(
|
request(
|
||||||
get,
|
get,
|
||||||
uri(PathPrefix ++ ["authentication", "password-based:built-in-database", "users"]) ++ "?page=2&limit=2"),
|
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)),
|
||||||
|
@ -440,10 +453,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, []).
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue