%%-------------------------------------------------------------------- %% Copyright (c) 2023-2024 EMQ Technologies Co., Ltd. All Rights Reserved. %%-------------------------------------------------------------------- -module(emqx_dashboard_rbac). -include_lib("emqx_dashboard/include/emqx_dashboard.hrl"). -export([ check_rbac/3, role/1, valid_dashboard_role/1, valid_api_role/1 ]). -dialyzer({nowarn_function, role/1}). %%===================================================================== %% API check_rbac(Req, Username, Extra) -> Role = role(Extra), 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, Username); _ -> false end. %% For compatibility role(#?ADMIN{role = undefined}) -> ?ROLE_SUPERUSER; role(#?ADMIN{role = Role}) -> Role; %% For compatibility role([]) -> ?ROLE_SUPERUSER; role(#{role := Role}) -> Role; role(Role) when is_binary(Role) -> Role. valid_dashboard_role(Role) -> valid_role(dashboard, Role). valid_api_role(Role) -> valid_role(api, Role). %% =================================================================== valid_role(Type, Role) -> case lists:member(Role, role_list(Type)) of true -> ok; _ -> {error, <<"Role does not exist">>} end. %% =================================================================== check_rbac(?ROLE_SUPERUSER, _, _, _) -> true; check_rbac(?ROLE_VIEWER, <<"GET">>, _, _) -> true; check_rbac(?ROLE_API_PUBLISHER, <<"POST">>, <<"/publish">>, _) -> true; check_rbac(?ROLE_API_PUBLISHER, <<"POST">>, <<"/publish/bulk">>, _) -> true; %% everyone should allow to logout check_rbac(?ROLE_VIEWER, <<"POST">>, <<"/logout">>, _) -> true; %% viewer should allow to change self password, %% superuser should allow to change any user check_rbac(?ROLE_VIEWER, <<"POST">>, <<"/users/", SubPath/binary>>, Username) -> case binary:split(SubPath, <<"/">>, [global]) of [Username, <<"change_pwd">>] -> true; _ -> false end; check_rbac(_, _, _, _) -> false. role_list(dashboard) -> [?ROLE_VIEWER, ?ROLE_SUPERUSER]; role_list(api) -> [?ROLE_API_VIEWER, ?ROLE_API_PUBLISHER, ?ROLE_API_SUPERUSER].