diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl b/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl index 48274b93b1..e78c777bee 100644 --- a/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl +++ b/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl @@ -123,8 +123,9 @@ dispatcher() -> {"/vhosts/:vhost/connections", rabbit_mgmt_wm_connections_vhost, []}, %% /channels/:channel is already taken, we cannot use our standard scheme here {"/vhosts/:vhost/channels", rabbit_mgmt_wm_channels_vhost, []}, - {"/users", rabbit_mgmt_wm_users, []}, {"/users/bulk-delete", rabbit_mgmt_wm_users_bulk_delete, []}, + {"/users/without-permissions", rabbit_mgmt_wm_users, [without_permissions]}, + {"/users", rabbit_mgmt_wm_users, [all]}, {"/users/:user", rabbit_mgmt_wm_user, []}, {"/users/:user/permissions", rabbit_mgmt_wm_permissions_user, []}, {"/users/:user/topic-permissions", rabbit_mgmt_wm_topic_permissions_user, []}, diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_wm_definitions.erl b/deps/rabbitmq_management/src/rabbit_mgmt_wm_definitions.erl index 543d29c50b..1c3416271e 100644 --- a/deps/rabbitmq_management/src/rabbit_mgmt_wm_definitions.erl +++ b/deps/rabbitmq_management/src/rabbit_mgmt_wm_definitions.erl @@ -72,7 +72,7 @@ all_definitions(ReqData, Context) -> rabbit_mgmt_util:reply( [{rabbit_version, rabbit_data_coercion:to_binary(Vsn)}] ++ filter( - [{users, rabbit_mgmt_wm_users:users()}, + [{users, rabbit_mgmt_wm_users:users(all)}, {vhosts, rabbit_mgmt_wm_vhosts:basic()}, {permissions, rabbit_mgmt_wm_permissions:permissions()}, {topic_permissions, rabbit_mgmt_wm_topic_permissions:topic_permissions()}, diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_wm_users.erl b/deps/rabbitmq_management/src/rabbit_mgmt_wm_users.erl index a99800f2ad..9e4839ed11 100644 --- a/deps/rabbitmq_management/src/rabbit_mgmt_wm_users.erl +++ b/deps/rabbitmq_management/src/rabbit_mgmt_wm_users.erl @@ -20,7 +20,7 @@ content_types_provided/2, is_authorized/2, allowed_methods/2]). -export([variances/2]). --export([users/0]). +-export([users/1]). -import(rabbit_misc, [pget/2]). @@ -31,8 +31,8 @@ init(_, _, _) -> {upgrade, protocol, cowboy_rest}. -rest_init(Req, _Config) -> - {ok, rabbit_mgmt_cors:set_headers(Req, ?MODULE), #context{}}. +rest_init(Req, [Mode]) -> + {ok, rabbit_mgmt_cors:set_headers(Req, ?MODULE), {Mode, #context{}}}. variances(Req, Context) -> {[<<"accept-encoding">>, <<"origin">>], Req, Context}. @@ -43,16 +43,28 @@ content_types_provided(ReqData, Context) -> allowed_methods(ReqData, Context) -> {[<<"HEAD">>, <<"GET">>, <<"OPTIONS">>], ReqData, Context}. -to_json(ReqData, Context) -> - rabbit_mgmt_util:reply_list(users(), ReqData, Context). +to_json(ReqData, {Mode, Context}) -> + rabbit_mgmt_util:reply_list(users(Mode), ReqData, Context). -is_authorized(ReqData, Context) -> - rabbit_mgmt_util:is_authorized_admin(ReqData, Context). +is_authorized(ReqData, {Mode, Context}) -> + {Res, Req2, Context2} = rabbit_mgmt_util:is_authorized_admin(ReqData, Context), + {Res, Req2, {Mode, Context2}}. %%-------------------------------------------------------------------- -users() -> +users(all) -> [begin {ok, User} = rabbit_auth_backend_internal:lookup_user(pget(user, U)), rabbit_mgmt_format:internal_user(User) - end || U <- rabbit_auth_backend_internal:list_users()]. + end || U <- rabbit_auth_backend_internal:list_users()]; +users(without_permissions) -> + lists:foldl(fun(U, Acc) -> + Username = pget(user, U), + case rabbit_auth_backend_internal:list_user_permissions(Username) of + [] -> + {ok, User} = rabbit_auth_backend_internal:lookup_user(Username), + [rabbit_mgmt_format:internal_user(User) | Acc]; + _ -> + Acc + end + end, [], rabbit_auth_backend_internal:list_users()). diff --git a/deps/rabbitmq_management/test/rabbit_mgmt_http_SUITE.erl b/deps/rabbitmq_management/test/rabbit_mgmt_http_SUITE.erl index 888d91eefc..0a6ab01b0d 100644 --- a/deps/rabbitmq_management/test/rabbit_mgmt_http_SUITE.erl +++ b/deps/rabbitmq_management/test/rabbit_mgmt_http_SUITE.erl @@ -58,6 +58,7 @@ groups() -> vhosts_test, vhosts_trace_test, users_test, + without_permissions_users_test, users_bulk_delete_test, users_legacy_administrator_test, adding_a_user_with_password_test, @@ -386,6 +387,25 @@ users_test(Config) -> http_get(Config, "/users/myuser", ?NOT_FOUND), passed. +without_permissions_users_test(Config) -> + assert_item(#{name => <<"guest">>, tags => <<"administrator">>}, + http_get(Config, "/whoami")), + http_put(Config, "/users/myuser", [{password_hash, + <<"IECV6PZI/Invh0DL187KFpkO5Jc=">>}, + {tags, <<"management">>}], {group, '2xx'}), + Perms = [{configure, <<".*">>}, {write, <<".*">>}, {read, <<".*">>}], + http_put(Config, "/permissions/%2f/myuser", Perms, {group, '2xx'}), + http_put(Config, "/users/myuserwithoutpermissions", [{password_hash, + <<"IECV6PZI/Invh0DL187KFpkO5Jc=">>}, + {tags, <<"management">>}], {group, '2xx'}), + assert_list([#{name => <<"myuserwithoutpermissions">>, tags => <<"management">>, + hashing_algorithm => <<"rabbit_password_hashing_sha256">>, + password_hash => <<"IECV6PZI/Invh0DL187KFpkO5Jc=">>}], + http_get(Config, "/users/without-permissions")), + http_delete(Config, "/users/myuser", {group, '2xx'}), + http_delete(Config, "/users/myuserwithoutpermissions", {group, '2xx'}), + passed. + users_bulk_delete_test(Config) -> assert_item(#{name => <<"guest">>, tags => <<"administrator">>}, http_get(Config, "/whoami")),