diff options
author | Nuwan Sameera <nuwan.s@synergentl.com> | 2022-07-21 06:52:58 +0000 |
---|---|---|
committer | Mergify <37929162+mergify[bot]@users.noreply.github.com> | 2022-08-05 22:16:16 +0000 |
commit | 8e5f20e9cabf5ad9d64668c0690b2b033d34b172 (patch) | |
tree | d47ce258dae3a6e4cf31756093f6070b7d92f451 | |
parent | 5bbdbb021d6a75dfc27322733412a345156dcd8e (diff) | |
download | rabbitmq-server-git-8e5f20e9cabf5ad9d64668c0690b2b033d34b172.tar.gz |
Add delete connection by username feature
Format code
Fix whitespace, fix warning
Update API docs
Remove blank lines
Add get all connections by username
Fix method name issue
Enable GET method to get connections by username
Update API documentation
Modify list all connections of username method
Remove list_by_username method and modify get all connections of user API
Code formatting, break up lines for readability
Refactor code to use pattern matching more effectively
Typo
(cherry picked from commit 6eb2630f554433aeb88bdfe62917db2787fb4846)
5 files changed, 110 insertions, 5 deletions
diff --git a/deps/rabbitmq_management/priv/www/api/index.html b/deps/rabbitmq_management/priv/www/api/index.html index 52b450ff25..c45df32d72 100644 --- a/deps/rabbitmq_management/priv/www/api/index.html +++ b/deps/rabbitmq_management/priv/www/api/index.html @@ -334,6 +334,18 @@ vary: accept, accept-encoding, origin</pre> <tr> <td>X</td> <td></td> + <td>X</td> + <td></td> + <td class="path">/api/connections/username/<i>username</i></td> + <td> + A list of all open connections for a specific username. Use pagination parameters to filter connections. + DELETEing a resource will close all the connections for a username. Optionally set the + "X-Reason" header when DELETEing to provide a reason. + </td> + </tr> + <tr> + <td>X</td> + <td></td> <td></td> <td></td> <td class="path">/api/connections/<i>name</i>/channels</td> diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl b/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl index 53eb15660d..5b560053c0 100644 --- a/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl +++ b/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl @@ -114,6 +114,7 @@ dispatcher() -> {"/vhost-limits/:vhost", rabbit_mgmt_wm_limits, []}, {"/connections", rabbit_mgmt_wm_connections, []}, {"/connections/:connection", rabbit_mgmt_wm_connection, []}, + {"/connections/username/:username", rabbit_mgmt_wm_connection_user_name, []}, {"/connections/:connection/channels", rabbit_mgmt_wm_connection_channels, []}, {"/channels", rabbit_mgmt_wm_channels, []}, {"/channels/:channel", rabbit_mgmt_wm_channel, []}, diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_wm_connection.erl b/deps/rabbitmq_management/src/rabbit_mgmt_wm_connection.erl index 4aebeda354..1c212937bb 100644 --- a/deps/rabbitmq_management/src/rabbit_mgmt_wm_connection.erl +++ b/deps/rabbitmq_management/src/rabbit_mgmt_wm_connection.erl @@ -37,11 +37,13 @@ resource_exists(ReqData, Context) -> to_json(ReqData, Context) -> case rabbit_mgmt_util:disable_stats(ReqData) of false -> - rabbit_mgmt_util:reply( - maps:from_list(rabbit_mgmt_format:strip_pids(conn_stats(ReqData))), ReqData, Context); + ConnStats = conn_stats(ReqData), + ConnStatsWithoutPids = rabbit_mgmt_format:strip_pids(ConnStats), + ReplyData = maps:from_list(ConnStatsWithoutPids), + rabbit_mgmt_util:reply(ReplyData, ReqData, Context); true -> - rabbit_mgmt_util:reply([{name, rabbit_mgmt_util:id(connection, ReqData)}], - ReqData, Context) + ReplyData = [{name, rabbit_mgmt_util:id(connection, ReqData)}], + rabbit_mgmt_util:reply(ReplyData, ReqData, Context) end. delete_resource(ReqData, Context) -> diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_wm_connection_user_name.erl b/deps/rabbitmq_management/src/rabbit_mgmt_wm_connection_user_name.erl new file mode 100644 index 0000000000..ee8d8c243f --- /dev/null +++ b/deps/rabbitmq_management/src/rabbit_mgmt_wm_connection_user_name.erl @@ -0,0 +1,91 @@ +%% This Source Code Form is subject to the terms of the Mozilla Public +%% License, v. 2.0. If a copy of the MPL was not distributed with this +%% file, You can obtain one at https://mozilla.org/MPL/2.0/. +%% +%% Copyright (c) 2007-2022 VMware, Inc. or its affiliates. All rights reserved. +%% + +-module(rabbit_mgmt_wm_connection_user_name). + +-export([init/2, to_json/2, content_types_provided/2, + is_authorized/2, allowed_methods/2, delete_resource/2]). +-export([variances/2]). + +-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). +-include_lib("rabbit_common/include/rabbit.hrl"). + +%%-------------------------------------------------------------------- + +init(Req, _State) -> + {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. + +variances(Req, Context) -> + {[<<"accept-encoding">>, <<"origin">>], Req, Context}. + +content_types_provided(ReqData, Context) -> + {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. + +allowed_methods(ReqData, Context) -> + {[<<"HEAD">>, <<"GET">>, <<"DELETE">>, <<"OPTIONS">>], ReqData, Context}. + +to_json(ReqData, Context) -> + {ok, _Username, UserConns} = list_user_connections(ReqData), + FilteredConns = rabbit_mgmt_util:filter_tracked_conn_list(UserConns, ReqData, Context), + rabbit_mgmt_util:reply_list_or_paginate(FilteredConns, ReqData, Context). + +delete_resource(ReqData, Context) -> + delete_resource(list_user_connections(ReqData), ReqData, Context). + +delete_resource({ok, _Username, []}, ReqData, Context) -> + {true, ReqData, Context}; +delete_resource({ok, Username, UserConns}, ReqData, Context) -> + ok = close_user_connections(UserConns, Username, ReqData), + {true, ReqData, Context}. + +is_authorized(ReqData, Context) -> + try + UserConns = list_user_connections(ReqData), + rabbit_mgmt_util:is_authorized_user(ReqData, Context, UserConns) + catch + {error, invalid_range_parameters, Reason} -> + rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context) + end. + +%%-------------------------------------------------------------------- + +list_user_connections(ReqData) -> + Username = rabbit_mgmt_util:id(username, ReqData), + UserConns = rabbit_connection_tracking:list_of_user(Username), + {ok, Username, UserConns}. + +close_user_connections([], _Username, _ReqData) -> + ok; +close_user_connections([Conn | Rest], Username, ReqData) -> + ok = close_user_connection(Conn, Username, ReqData), + close_user_connections(Rest, Username, ReqData). + +close_user_connection(#tracked_connection{name = Name, pid = Pid, username = Username, type = Type}, Username, ReqData) when is_pid(Pid) -> + Conn = [{name, Name}, {pid, Pid}, {user, Username}, {type, Type}], + force_close_connection(ReqData, Conn, Pid); +close_user_connection(#tracked_connection{pid = undefined}, _Username, _ReqData) -> + ok; +close_user_connection(UnexpectedConn, Username, _ReqData) -> + rabbit_log:debug("~p Username: ~p", [?MODULE, Username]), + rabbit_log:debug("~p unexpected connection: ~p", [?MODULE, UnexpectedConn]), + ok. + +force_close_connection(ReqData, Conn, Pid) -> + Reason = case cowboy_req:header(<<"x-reason">>, ReqData) of + undefined -> "Closed via management plugin"; + V -> binary_to_list(V) + end, + case proplists:get_value(type, Conn) of + direct -> + amqp_direct_connection:server_close(Pid, 320, Reason); + network -> + rabbit_networking:close_connection(Pid, Reason); + _ -> + % best effort, this will work for connections to the stream plugin + gen_server:cast(Pid, {shutdown, Reason}) + end, + ok. diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_wm_connections.erl b/deps/rabbitmq_management/src/rabbit_mgmt_wm_connections.erl index c626b4ba17..65785c3421 100644 --- a/deps/rabbitmq_management/src/rabbit_mgmt_wm_connections.erl +++ b/deps/rabbitmq_management/src/rabbit_mgmt_wm_connections.erl @@ -14,7 +14,6 @@ -import(rabbit_misc, [pget/2]). -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). --include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- |