refactor: banned api (#5578)

This commit is contained in:
DDDHuang 2021-08-27 18:21:49 +08:00 committed by GitHub
parent 46fb99d44e
commit 9893c0263a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 175 additions and 3 deletions

View File

@ -126,8 +126,7 @@
-record(banned, {
who :: {clientid, binary()}
| {peerhost, inet:ip_address()}
| {username, binary()}
| {ip_address, inet:ip_address()},
| {username, binary()},
by :: binary(),
reason :: binary(),
at :: integer(),

View File

@ -33,8 +33,10 @@
-export([ check/1
, create/1
, look_up/1
, delete/1
, info/1
, format/1
]).
%% gen_server callbacks
@ -90,7 +92,31 @@ do_check(Who) when is_tuple(Who) ->
Until > erlang:system_time(second)
end.
-spec(create(emqx_types:banned()) -> ok).
format(#banned{who = Who0,
by = By,
reason = Reason,
at = At,
until = Until}) ->
{As, Who} = maybe_format_host(Who0),
#{
as => As,
who => Who,
by => By,
reason => Reason,
at => to_rfc3339(At),
until => to_rfc3339(Until)
}.
maybe_format_host({peerhost, Host}) ->
AddrBinary = list_to_binary(inet:ntoa(Host)),
{peerhost, AddrBinary};
maybe_format_host({As, Who}) ->
{As, Who}.
to_rfc3339(Timestamp) ->
list_to_binary(calendar:system_time_to_rfc3339(Timestamp, [{unit, second}])).
-spec(create(emqx_types:banned() | map()) -> ok).
create(#{who := Who,
by := By,
reason := Reason,
@ -104,6 +130,9 @@ create(#{who := Who,
create(Banned) when is_record(Banned, banned) ->
ekka_mnesia:dirty_write(?BANNED_TAB, Banned).
look_up(Who) ->
mnesia:dirty_read(?BANNED_TAB, Who).
-spec(delete({clientid, emqx_types:clientid()}
| {username, emqx_types:username()}
| {peerhost, emqx_types:peerhost()}) -> ok).

View File

@ -0,0 +1,144 @@
%%--------------------------------------------------------------------
%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%--------------------------------------------------------------------
-module(emqx_mgmt_api_banned).
-include_lib("emqx/include/emqx.hrl").
-include("emqx_mgmt.hrl").
-behaviour(minirest_api).
-export([api_spec/0]).
-export([ banned/2
, delete_banned/2
]).
-import(emqx_mgmt_util, [ page_params/0
, schema/1
, object_schema/1
, page_object_schema/1
, properties/1
, error_schema/1
]).
-export([format/1]).
-define(TAB, emqx_banned).
api_spec() ->
{[banned_api(), delete_banned_api()], []}.
-define(BANNED_TYPES, [clientid, username, peerhost]).
properties() ->
properties([
{as, string, <<"Banned type clientid, username, peerhost">>, [clientid, username, peerhost]},
{who, string, <<"Client info as banned type">>},
{by, integer, <<"Commander">>},
{reason, string, <<"Banned reason">>},
{at, integer, <<"Create banned time. Nullable, rfc3339, default is now">>},
{until, string, <<"Cancel banned time. Nullable, rfc3339, default is now + 5 minute">>}
]).
banned_api() ->
Path = "/banned",
MetaData = #{
get => #{
description => <<"List banned">>,
parameters => page_params(),
responses => #{
<<"200">> =>
page_object_schema(properties())}},
post => #{
description => <<"Create banned">>,
'requestBody' => object_schema(properties()),
responses => #{
<<"200">> => schema(<<"Create success">>)}}},
{Path, MetaData, banned}.
delete_banned_api() ->
Path = "/banned/:as/:who",
MetaData = #{
delete => #{
description => <<"Delete banned">>,
parameters => [
#{
name => as,
in => path,
required => true,
description => <<"Banned type">>,
schema => #{type => string, enum => ?BANNED_TYPES}
},
#{
name => who,
in => path,
required => true,
description => <<"Client info as banned type">>,
schema => #{type => string}
}
],
responses => #{
<<"200">> => schema(<<"Delete banned success">>),
<<"404">> => error_schema(<<"Banned not found">>)}}},
{Path, MetaData, delete_banned}.
banned(get, #{query_string := Params}) ->
Response = emqx_mgmt_api:paginate(?TAB, Params, fun format/1),
{200, Response};
banned(post, #{body := Body}) ->
Banned = trans_param(Body),
_ = emqx_banned:create(Banned),
{200}.
delete_banned(delete, #{bindings := Params}) ->
Who = trans_who(Params),
case emqx_banned:look_up(Who) of
[] ->
As0 = maps:get(as, Params),
Who0 = maps:get(who, Params),
Message = list_to_binary(io_lib:format("~p: ~p not found", [As0, Who0])),
{404, #{code => 'RESOURCE_NOT_FOUND', message => Message}};
_ ->
ok = emqx_banned:delete(Who),
{200}
end.
trans_param(Params) ->
Who = trans_who(Params),
By = maps:get(<<"by">>, Params, <<"mgmt_api">>),
Reason = maps:get(<<"reason">>, Params, <<"">>),
At = maps:get(<<"at">>, Params, erlang:system_time(second)),
Until = maps:get(<<"until">>, Params, At + 5 * 60),
#banned{
who = Who,
by = By,
reason = Reason,
at = At,
until = Until
}.
trans_who(#{as := As, who := Who}) ->
trans_who(#{<<"as">> => As, <<"who">> => Who});
trans_who(#{<<"as">> := <<"peerhost">>, <<"who">> := Peerhost0}) ->
{ok, Peerhost} = inet:parse_address(binary_to_list(Peerhost0)),
{peerhost, Peerhost};
trans_who(#{<<"as">> := As, <<"who">> := Who}) ->
{binary_to_atom(As, utf8), Who}.
format(Banned) ->
emqx_banned:format(Banned).