fix(RBAC): allow read-only users to logout

This commit is contained in:
firest 2023-09-22 11:06:24 +08:00
parent d6a97987e2
commit 681e57dee6
3 changed files with 34 additions and 7 deletions

View File

@ -28,7 +28,7 @@
-export([error_codes/1, error_codes/2]). -export([error_codes/1, error_codes/2]).
-export([file_schema/1]). -export([file_schema/1]).
-export([base_path/0]). -export([base_path/0]).
-export([relative_uri/1]). -export([relative_uri/1, get_relative_uri/1]).
-export([compose_filters/2]). -export([compose_filters/2]).
-export([ -export([
@ -212,6 +212,12 @@ base_path() ->
relative_uri(Uri) -> relative_uri(Uri) ->
base_path() ++ Uri. base_path() ++ Uri.
-spec get_relative_uri(uri_string:uri_string()) -> {ok, uri_string:uri_string()} | error.
get_relative_uri(<<?BASE_PATH, Path/binary>>) ->
{ok, Path};
get_relative_uri(_Path) ->
error.
file_schema(FileName) -> file_schema(FileName) ->
#{ #{
content => #{ content => #{

View File

@ -12,9 +12,15 @@
%%===================================================================== %%=====================================================================
%% API %% API
check_rbac(Req, Extra) -> check_rbac(Req, Extra) ->
Method = cowboy_req:method(Req),
Role = role(Extra), Role = role(Extra),
check_rbac_with_method(Role, Method). Method = cowboy_req:method(Req),
AbsPath = cowboy_req:path(Req),
case emqx_dashboard_swagger:get_relative_uri(AbsPath) of
{ok, Path} ->
check_rbac(Role, Method, Path);
_ ->
false
end.
%% For compatibility %% For compatibility
role(#?ADMIN{role = undefined}) -> role(#?ADMIN{role = undefined}) ->
@ -35,11 +41,14 @@ valid_role(Role) ->
{error, <<"Role does not exist">>} {error, <<"Role does not exist">>}
end. end.
%% =================================================================== %% ===================================================================
check_rbac_with_method(?ROLE_SUPERUSER, _) -> check_rbac(?ROLE_SUPERUSER, _, _) ->
true; true;
check_rbac_with_method(?ROLE_VIEWER, <<"GET">>) -> check_rbac(?ROLE_VIEWER, <<"GET">>, _) ->
true; true;
check_rbac_with_method(_, _) -> %% this API is a special case
check_rbac(?ROLE_VIEWER, <<"POST">>, <<"/logout">>) ->
true;
check_rbac(_, _, _) ->
false. false.
role_list() -> role_list() ->

View File

@ -136,7 +136,8 @@ t_clean_token(_) ->
NewDesc = <<"new desc">>, NewDesc = <<"new desc">>,
{ok, _} = emqx_dashboard_admin:add_user(Username, Password, ?ROLE_SUPERUSER, Desc), {ok, _} = emqx_dashboard_admin:add_user(Username, Password, ?ROLE_SUPERUSER, Desc),
{ok, Token} = emqx_dashboard_admin:sign_token(Username, Password), {ok, Token} = emqx_dashboard_admin:sign_token(Username, Password),
FakeReq = #{method => <<"GET">>}, FakePath = erlang:list_to_binary(emqx_dashboard_swagger:relative_uri("/fake")),
FakeReq = #{method => <<"GET">>, path => FakePath},
{ok, Username} = emqx_dashboard_admin:verify_token(FakeReq, Token), {ok, Username} = emqx_dashboard_admin:verify_token(FakeReq, Token),
%% change description %% change description
{ok, _} = emqx_dashboard_admin:update_user(Username, ?ROLE_SUPERUSER, NewDesc), {ok, _} = emqx_dashboard_admin:update_user(Username, ?ROLE_SUPERUSER, NewDesc),
@ -148,6 +149,17 @@ t_clean_token(_) ->
{error, not_found} = emqx_dashboard_admin:verify_token(FakeReq, Token), {error, not_found} = emqx_dashboard_admin:verify_token(FakeReq, Token),
ok. ok.
t_login_out(_) ->
Username = <<"admin_token">>,
Password = <<"public_www1">>,
Desc = <<"desc">>,
{ok, _} = emqx_dashboard_admin:add_user(Username, Password, ?ROLE_SUPERUSER, Desc),
{ok, Token} = emqx_dashboard_admin:sign_token(Username, Password),
FakePath = erlang:list_to_binary(emqx_dashboard_swagger:relative_uri("/logout")),
FakeReq = #{method => <<"POST">>, path => FakePath},
{ok, Username} = emqx_dashboard_admin:verify_token(FakeReq, Token),
ok.
add_default_superuser() -> add_default_superuser() ->
{ok, _NewUser} = emqx_dashboard_admin:add_user( {ok, _NewUser} = emqx_dashboard_admin:add_user(
?DEFAULT_SUPERUSER, ?DEFAULT_SUPERUSER,