Skip to content

Commit 8e5f20e

Browse files
Nuwan Sameeramergify[bot]
authored andcommitted
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 6eb2630)
1 parent 5bbdbb0 commit 8e5f20e

File tree

5 files changed

+110
-5
lines changed

5 files changed

+110
-5
lines changed

deps/rabbitmq_management/priv/www/api/index.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,18 @@ <h2>Reference</h2>
331331
DELETEing to provide a reason.
332332
</td>
333333
</tr>
334+
<tr>
335+
<td>X</td>
336+
<td></td>
337+
<td>X</td>
338+
<td></td>
339+
<td class="path">/api/connections/username/<i>username</i></td>
340+
<td>
341+
A list of all open connections for a specific username. Use pagination parameters to filter connections.
342+
DELETEing a resource will close all the connections for a username. Optionally set the
343+
"X-Reason" header when DELETEing to provide a reason.
344+
</td>
345+
</tr>
334346
<tr>
335347
<td>X</td>
336348
<td></td>

deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ dispatcher() ->
114114
{"/vhost-limits/:vhost", rabbit_mgmt_wm_limits, []},
115115
{"/connections", rabbit_mgmt_wm_connections, []},
116116
{"/connections/:connection", rabbit_mgmt_wm_connection, []},
117+
{"/connections/username/:username", rabbit_mgmt_wm_connection_user_name, []},
117118
{"/connections/:connection/channels", rabbit_mgmt_wm_connection_channels, []},
118119
{"/channels", rabbit_mgmt_wm_channels, []},
119120
{"/channels/:channel", rabbit_mgmt_wm_channel, []},

deps/rabbitmq_management/src/rabbit_mgmt_wm_connection.erl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ resource_exists(ReqData, Context) ->
3737
to_json(ReqData, Context) ->
3838
case rabbit_mgmt_util:disable_stats(ReqData) of
3939
false ->
40-
rabbit_mgmt_util:reply(
41-
maps:from_list(rabbit_mgmt_format:strip_pids(conn_stats(ReqData))), ReqData, Context);
40+
ConnStats = conn_stats(ReqData),
41+
ConnStatsWithoutPids = rabbit_mgmt_format:strip_pids(ConnStats),
42+
ReplyData = maps:from_list(ConnStatsWithoutPids),
43+
rabbit_mgmt_util:reply(ReplyData, ReqData, Context);
4244
true ->
43-
rabbit_mgmt_util:reply([{name, rabbit_mgmt_util:id(connection, ReqData)}],
44-
ReqData, Context)
45+
ReplyData = [{name, rabbit_mgmt_util:id(connection, ReqData)}],
46+
rabbit_mgmt_util:reply(ReplyData, ReqData, Context)
4547
end.
4648

4749
delete_resource(ReqData, Context) ->
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
%% This Source Code Form is subject to the terms of the Mozilla Public
2+
%% License, v. 2.0. If a copy of the MPL was not distributed with this
3+
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
%%
5+
%% Copyright (c) 2007-2022 VMware, Inc. or its affiliates. All rights reserved.
6+
%%
7+
8+
-module(rabbit_mgmt_wm_connection_user_name).
9+
10+
-export([init/2, to_json/2, content_types_provided/2,
11+
is_authorized/2, allowed_methods/2, delete_resource/2]).
12+
-export([variances/2]).
13+
14+
-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").
15+
-include_lib("rabbit_common/include/rabbit.hrl").
16+
17+
%%--------------------------------------------------------------------
18+
19+
init(Req, _State) ->
20+
{cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}.
21+
22+
variances(Req, Context) ->
23+
{[<<"accept-encoding">>, <<"origin">>], Req, Context}.
24+
25+
content_types_provided(ReqData, Context) ->
26+
{rabbit_mgmt_util:responder_map(to_json), ReqData, Context}.
27+
28+
allowed_methods(ReqData, Context) ->
29+
{[<<"HEAD">>, <<"GET">>, <<"DELETE">>, <<"OPTIONS">>], ReqData, Context}.
30+
31+
to_json(ReqData, Context) ->
32+
{ok, _Username, UserConns} = list_user_connections(ReqData),
33+
FilteredConns = rabbit_mgmt_util:filter_tracked_conn_list(UserConns, ReqData, Context),
34+
rabbit_mgmt_util:reply_list_or_paginate(FilteredConns, ReqData, Context).
35+
36+
delete_resource(ReqData, Context) ->
37+
delete_resource(list_user_connections(ReqData), ReqData, Context).
38+
39+
delete_resource({ok, _Username, []}, ReqData, Context) ->
40+
{true, ReqData, Context};
41+
delete_resource({ok, Username, UserConns}, ReqData, Context) ->
42+
ok = close_user_connections(UserConns, Username, ReqData),
43+
{true, ReqData, Context}.
44+
45+
is_authorized(ReqData, Context) ->
46+
try
47+
UserConns = list_user_connections(ReqData),
48+
rabbit_mgmt_util:is_authorized_user(ReqData, Context, UserConns)
49+
catch
50+
{error, invalid_range_parameters, Reason} ->
51+
rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context)
52+
end.
53+
54+
%%--------------------------------------------------------------------
55+
56+
list_user_connections(ReqData) ->
57+
Username = rabbit_mgmt_util:id(username, ReqData),
58+
UserConns = rabbit_connection_tracking:list_of_user(Username),
59+
{ok, Username, UserConns}.
60+
61+
close_user_connections([], _Username, _ReqData) ->
62+
ok;
63+
close_user_connections([Conn | Rest], Username, ReqData) ->
64+
ok = close_user_connection(Conn, Username, ReqData),
65+
close_user_connections(Rest, Username, ReqData).
66+
67+
close_user_connection(#tracked_connection{name = Name, pid = Pid, username = Username, type = Type}, Username, ReqData) when is_pid(Pid) ->
68+
Conn = [{name, Name}, {pid, Pid}, {user, Username}, {type, Type}],
69+
force_close_connection(ReqData, Conn, Pid);
70+
close_user_connection(#tracked_connection{pid = undefined}, _Username, _ReqData) ->
71+
ok;
72+
close_user_connection(UnexpectedConn, Username, _ReqData) ->
73+
rabbit_log:debug("~p Username: ~p", [?MODULE, Username]),
74+
rabbit_log:debug("~p unexpected connection: ~p", [?MODULE, UnexpectedConn]),
75+
ok.
76+
77+
force_close_connection(ReqData, Conn, Pid) ->
78+
Reason = case cowboy_req:header(<<"x-reason">>, ReqData) of
79+
undefined -> "Closed via management plugin";
80+
V -> binary_to_list(V)
81+
end,
82+
case proplists:get_value(type, Conn) of
83+
direct ->
84+
amqp_direct_connection:server_close(Pid, 320, Reason);
85+
network ->
86+
rabbit_networking:close_connection(Pid, Reason);
87+
_ ->
88+
% best effort, this will work for connections to the stream plugin
89+
gen_server:cast(Pid, {shutdown, Reason})
90+
end,
91+
ok.

deps/rabbitmq_management/src/rabbit_mgmt_wm_connections.erl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
-import(rabbit_misc, [pget/2]).
1515

1616
-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").
17-
-include_lib("rabbit_common/include/rabbit.hrl").
1817

1918
%%--------------------------------------------------------------------
2019

0 commit comments

Comments
 (0)