feat(dashboard): Support swagger dashboard API

This commit is contained in:
Turtle 2021-07-26 13:57:52 +08:00 committed by turtleDeng
parent 569d54a4c0
commit eac9420170
2 changed files with 207 additions and 76 deletions

View File

@ -1,5 +1,5 @@
##-------------------------------------------------------------------- ##--------------------------------------------------------------------
## Dashboard for EMQ X ## EMQ X Dashboard
##-------------------------------------------------------------------- ##--------------------------------------------------------------------
emqx_dashboard:{ emqx_dashboard:{
@ -20,7 +20,7 @@ emqx_dashboard:{
## , ## ,
## { ## {
## protocol: https ## protocol: https
## port: 8081 ## port: 18084
## acceptors: 2 ## acceptors: 2
## backlog: 512 ## backlog: 512
## send_timeout: 15s ## send_timeout: 15s

View File

@ -16,95 +16,226 @@
-module(emqx_dashboard_api). -module(emqx_dashboard_api).
-behaviour(minirest_api).
-include("emqx_dashboard.hrl"). -include("emqx_dashboard.hrl").
-rest_api(#{name => auth_user, -import(emqx_mgmt_util, [ response_schema/1
method => 'POST', , response_schema/2
path => "/auth", , request_body_schema/1
func => auth, , response_array_schema/2
descr => "Authenticate an user" ]).
}).
-rest_api(#{name => create_user, -export([api_spec/0]).
method => 'POST',
path => "/users/",
func => create,
descr => "Create an user"
}).
-rest_api(#{name => list_users, -export([ auth/2
method => 'GET', , users/2
path => "/users/", , user/2
func => list,
descr => "List users"
}).
-rest_api(#{name => update_user,
method => 'PUT',
path => "/users/:bin:name",
func => update,
descr => "Update an user"
}).
-rest_api(#{name => delete_user,
method => 'DELETE',
path => "/users/:bin:name",
func => delete,
descr => "Delete an user"
}).
-rest_api(#{name => change_pwd,
method => 'PUT',
path => "/change_pwd/:bin:username",
func => change_pwd,
descr => "Change password for an user"
}).
-export([ list/2
, create/2
, update/2
, delete/2
, auth/2
, change_pwd/2 , change_pwd/2
]). ]).
api_spec() ->
{[auth_api(), users_api(), user_api(), change_pwd_api()], schemas()}.
schemas() ->
[#{auth => #{
type => object,
properties => #{
username => #{
type => string,
description => <<"Username">>},
password => #{
type => string,
description => <<"password">>}
}
}},
#{show_user => #{
type => object,
properties => #{
username => #{
type => string,
description => <<"Username">>},
tag => #{
type => string,
description => <<"Tag">>}
}
}},
#{create_user => #{
type => object,
properties => #{
username => #{
type => string,
description => <<"Username">>},
password => #{
type => string,
description => <<"Password">>},
tag => #{
type => string,
description => <<"Tag">>}
}
}}].
auth_api() ->
Metadata = #{
post => #{
description => <<"Dashboard Auth">>,
'requestBody' => request_body_schema(auth),
responses => #{
<<"200">> =>
response_schema(<<"Dashboard Auth successfully">>),
<<"400">> => bad_request()
},
security => []
}
},
{"/auth", Metadata, auth}.
users_api() ->
Metadata = #{
get => #{
description => <<"Get dashboard users">>,
responses => #{
<<"200">> => response_array_schema(<<"">>, show_user)
}
}
},
{"/users", Metadata, users}.
user_api() ->
Metadata = #{
delete => #{
description => <<"Delete dashboard users">>,
responses => #{
<<"200">> => response_schema(<<"Delete User successfully">>),
<<"400">> => bad_request()
}
},
put => #{
description => <<"Update dashboard users">>,
'requestBody' => request_body_schema(#{
type => object,
properties => #{
tags => #{
type => string
}
}
}),
responses => #{
<<"200">> => response_schema(<<"Update Users successfully">>),
<<"400">> => bad_request()
}
},
post => #{
description => <<"Create dashboard users">>,
'requestBody' => request_body_schema(create_user),
responses => #{
<<"200">> => response_schema(<<"Create Users successfully">>),
<<"400">> => bad_request()
}
}
},
{"/users/:username", Metadata, user}.
change_pwd_api() ->
Metadata = #{
put => #{
description => <<"Update dashboard users password">>,
'requestBody' => request_body_schema(#{
type => object,
properties => #{
old_pwd => #{
type => string
},
new_pwd => #{
type => string
}
}
}),
responses => #{
<<"200">> => response_schema(<<"Update Users password successfully">>),
<<"400">> => bad_request()
}
}
},
{"/change_pwd/:username", Metadata, change_pwd}.
-define(EMPTY(V), (V == undefined orelse V == <<>>)). -define(EMPTY(V), (V == undefined orelse V == <<>>)).
auth(_Bindings, Params) -> auth(post, Request) ->
Username = proplists:get_value(<<"username">>, Params), {ok, Body, _} = cowboy_req:read_body(Request),
Password = proplists:get_value(<<"password">>, Params), Params = emqx_json:decode(Body, [return_maps]),
return(emqx_dashboard_admin:check(Username, Password)). Username = maps:get(<<"username">>, Params),
Password = maps:get(<<"password">>, Params),
case emqx_dashboard_admin:check(Username, Password) of
ok ->
{200};
{error, Reason} ->
{400, #{code => <<"AUTH_FAIL">>, message => Reason}}
end.
change_pwd(#{username := Username}, Params) -> users(get, _Request) ->
OldPwd = proplists:get_value(<<"old_pwd">>, Params), {200, [row(User) || User <- emqx_dashboard_admin:all_users()]}.
NewPwd = proplists:get_value(<<"new_pwd">>, Params),
return(emqx_dashboard_admin:change_password(Username, OldPwd, NewPwd)).
create(_Bindings, Params) -> user(put, Request) ->
Username = proplists:get_value(<<"username">>, Params), Username = cowboy_req:binding(username, Request),
Password = proplists:get_value(<<"password">>, Params), {ok, Body, _} = cowboy_req:read_body(Request),
Tags = proplists:get_value(<<"tags">>, Params), Params = emqx_json:decode(Body, [return_maps]),
return(case ?EMPTY(Username) orelse ?EMPTY(Password) of Tags = maps:get(<<"tags">>, Params),
true -> {error, <<"Username or password undefined">>}; case emqx_dashboard_admin:update_user(Username, Tags) of
false -> emqx_dashboard_admin:add_user(Username, Password, Tags) ok -> {200};
end). {error, Reason} ->
{400, #{code => <<"UPDATE_FAIL">>, message => Reason}}
end;
list(_Bindings, _Params) -> user(delete, Request) ->
return({ok, [row(User) || User <- emqx_dashboard_admin:all_users()]}). Username = cowboy_req:binding(username, Request),
case Username == <<"admin">> of
true -> {400, #{code => <<"CONNOT_DELETE_ADMIN">>,
message => <<"Cannot delete admin">>}};
false ->
_ = emqx_dashboard_admin:remove_user(Username),
{200}
end;
update(#{name := Username}, Params) -> user(post, Request) ->
Tags = proplists:get_value(<<"tags">>, Params), {ok, Body, _} = cowboy_req:read_body(Request),
return(emqx_dashboard_admin:update_user(Username, Tags)). Params = emqx_json:decode(Body, [return_maps]),
Tags = maps:get(<<"tags">>, Params),
Username = maps:get(<<"username">>, Params),
Password = maps:get(<<"password">>, Params),
case ?EMPTY(Username) orelse ?EMPTY(Password) of
true ->
{400, #{code => <<"CREATE_USER_FAIL">>,
message => <<"Username or password undefined">>}};
false ->
case emqx_dashboard_admin:add_user(Username, Password, Tags) of
ok -> {200};
{error, Reason} ->
{400, #{code => <<"CREATE_USER_FAIL">>, message => Reason}}
end
end.
delete(#{name := <<"admin">>}, _Params) -> change_pwd(put, Request) ->
return({error, <<"Cannot delete admin">>}); Username = cowboy_req:binding(username, Request),
{ok, Body, _} = cowboy_req:read_body(Request),
delete(#{name := Username}, _Params) -> Params = emqx_json:decode(Body, [return_maps]),
return(emqx_dashboard_admin:remove_user(Username)). OldPwd = maps:get(<<"old_pwd">>, Params),
NewPwd = maps:get(<<"new_pwd">>, Params),
case emqx_dashboard_admin:change_password(Username, OldPwd, NewPwd) of
ok -> {200};
{error, Reason} ->
{400, #{code => <<"CHANGE_PWD_FAIL">>, message => Reason}}
end.
row(#mqtt_admin{username = Username, tags = Tags}) -> row(#mqtt_admin{username = Username, tags = Tags}) ->
#{username => Username, tags => Tags}. #{username => Username, tags => Tags}.
return(_) -> bad_request() ->
%% TODO: V5 API response_schema(<<"Bad Request">>,
ok. #{
type => object,
properties => #{
message => #{type => string},
code => #{type => string}
}
}).