refactor: refactor emqx_authz
Signed-off-by: zhanghongtong <rory-z@outlook.com>
This commit is contained in:
parent
caef8cb381
commit
6b313a60d4
|
@ -51,33 +51,41 @@ init() ->
|
|||
lookup() ->
|
||||
{_M, _F, [A]}= find_action_in_hooks(),
|
||||
A.
|
||||
lookup(Id) ->
|
||||
try find_source_by_id(Id, lookup()) of
|
||||
lookup(Type) ->
|
||||
try find_source_by_type(atom(Type), lookup()) of
|
||||
{_, Source} -> Source
|
||||
catch
|
||||
error:Reason -> {error, Reason}
|
||||
end.
|
||||
|
||||
move(Id, Position) ->
|
||||
emqx:update_config(?CONF_KEY_PATH, {move, Id, Position}).
|
||||
move(Type, #{<<"before">> := Before}) ->
|
||||
emqx:update_config(?CONF_KEY_PATH, {move, atom(Type), #{<<"before">> => atom(Before)}});
|
||||
move(Type, #{<<"after">> := After}) ->
|
||||
emqx:update_config(?CONF_KEY_PATH, {move, atom(Type), #{<<"after">> => atom(After)}});
|
||||
move(Type, Position) ->
|
||||
emqx:update_config(?CONF_KEY_PATH, {move, atom(Type), Position}).
|
||||
|
||||
update({replace_once, Type}, Sources) ->
|
||||
emqx:update_config(?CONF_KEY_PATH, {{replace_once, atom(Type)}, Sources});
|
||||
update({delete_once, Type}, Sources) ->
|
||||
emqx:update_config(?CONF_KEY_PATH, {{delete_once, atom(Type)}, Sources});
|
||||
update(Cmd, Sources) ->
|
||||
emqx:update_config(?CONF_KEY_PATH, {Cmd, Sources}).
|
||||
|
||||
pre_config_update({move, Id, <<"top">>}, Conf) when is_list(Conf) ->
|
||||
{Index, _} = find_source_by_id(Id),
|
||||
pre_config_update({move, Type, <<"top">>}, Conf) when is_list(Conf) ->
|
||||
{Index, _} = find_source_by_type(Type),
|
||||
{List1, List2} = lists:split(Index, Conf),
|
||||
{ok, [lists:nth(Index, Conf)] ++ lists:droplast(List1) ++ List2};
|
||||
|
||||
pre_config_update({move, Id, <<"bottom">>}, Conf) when is_list(Conf) ->
|
||||
{Index, _} = find_source_by_id(Id),
|
||||
pre_config_update({move, Type, <<"bottom">>}, Conf) when is_list(Conf) ->
|
||||
{Index, _} = find_source_by_type(Type),
|
||||
{List1, List2} = lists:split(Index, Conf),
|
||||
{ok, lists:droplast(List1) ++ List2 ++ [lists:nth(Index, Conf)]};
|
||||
|
||||
pre_config_update({move, Id, #{<<"before">> := BeforeId}}, Conf) when is_list(Conf) ->
|
||||
{Index1, _} = find_source_by_id(Id),
|
||||
pre_config_update({move, Type, #{<<"before">> := Before}}, Conf) when is_list(Conf) ->
|
||||
{Index1, _} = find_source_by_type(Type),
|
||||
Conf1 = lists:nth(Index1, Conf),
|
||||
{Index2, _} = find_source_by_id(BeforeId),
|
||||
{Index2, _} = find_source_by_type(Before),
|
||||
Conf2 = lists:nth(Index2, Conf),
|
||||
|
||||
{List1, List2} = lists:split(Index2, Conf),
|
||||
|
@ -85,10 +93,10 @@ pre_config_update({move, Id, #{<<"before">> := BeforeId}}, Conf) when is_list(Co
|
|||
++ [Conf1] ++ [Conf2]
|
||||
++ lists:delete(Conf1, List2)};
|
||||
|
||||
pre_config_update({move, Id, #{<<"after">> := AfterId}}, Conf) when is_list(Conf) ->
|
||||
{Index1, _} = find_source_by_id(Id),
|
||||
pre_config_update({move, Type, #{<<"after">> := After}}, Conf) when is_list(Conf) ->
|
||||
{Index1, _} = find_source_by_type(Type),
|
||||
Conf1 = lists:nth(Index1, Conf),
|
||||
{Index2, _} = find_source_by_id(AfterId),
|
||||
{Index2, _} = find_source_by_type(After),
|
||||
|
||||
{List1, List2} = lists:split(Index2, Conf),
|
||||
{ok, lists:delete(Conf1, List1)
|
||||
|
@ -99,34 +107,37 @@ pre_config_update({head, Sources}, Conf) when is_list(Sources), is_list(Conf) ->
|
|||
{ok, Sources ++ Conf};
|
||||
pre_config_update({tail, Sources}, Conf) when is_list(Sources), is_list(Conf) ->
|
||||
{ok, Conf ++ Sources};
|
||||
pre_config_update({{replace_once, Id}, Source}, Conf) when is_map(Source), is_list(Conf) ->
|
||||
{Index, _} = find_source_by_id(Id),
|
||||
pre_config_update({{replace_once, Type}, Source}, Conf) when is_map(Source), is_list(Conf) ->
|
||||
{Index, _} = find_source_by_type(Type),
|
||||
{List1, List2} = lists:split(Index, Conf),
|
||||
{ok, lists:droplast(List1) ++ [Source] ++ List2};
|
||||
pre_config_update({{delete_once, Type}, _Source}, Conf) when is_list(Conf) ->
|
||||
{_, Source} = find_source_by_type(Type),
|
||||
{ok, lists:delete(Source, Conf)};
|
||||
pre_config_update({_, Sources}, _Conf) when is_list(Sources)->
|
||||
%% overwrite the entire config!
|
||||
{ok, Sources}.
|
||||
|
||||
post_config_update(_, undefined, _Conf, _AppEnvs) ->
|
||||
ok;
|
||||
post_config_update({move, Id, <<"top">>}, _NewSources, _OldSources, _AppEnvs) ->
|
||||
post_config_update({move, Type, <<"top">>}, _NewSources, _OldSources, _AppEnvs) ->
|
||||
InitedSources = lookup(),
|
||||
{Index, Source} = find_source_by_id(Id, InitedSources),
|
||||
{Index, Source} = find_source_by_type(Type, InitedSources),
|
||||
{Sources1, Sources2 } = lists:split(Index, InitedSources),
|
||||
Sources3 = [Source] ++ lists:droplast(Sources1) ++ Sources2,
|
||||
ok = emqx_hooks:put('client.authorize', {?MODULE, authorize, [Sources3]}, -1),
|
||||
ok = emqx_authz_cache:drain_cache();
|
||||
post_config_update({move, Id, <<"bottom">>}, _NewSources, _OldSources, _AppEnvs) ->
|
||||
post_config_update({move, Type, <<"bottom">>}, _NewSources, _OldSources, _AppEnvs) ->
|
||||
InitedSources = lookup(),
|
||||
{Index, Source} = find_source_by_id(Id, InitedSources),
|
||||
{Index, Source} = find_source_by_type(Type, InitedSources),
|
||||
{Sources1, Sources2 } = lists:split(Index, InitedSources),
|
||||
Sources3 = lists:droplast(Sources1) ++ Sources2 ++ [Source],
|
||||
ok = emqx_hooks:put('client.authorize', {?MODULE, authorize, [Sources3]}, -1),
|
||||
ok = emqx_authz_cache:drain_cache();
|
||||
post_config_update({move, Id, #{<<"before">> := BeforeId}}, _NewSources, _OldSources, _AppEnvs) ->
|
||||
post_config_update({move, Type, #{<<"before">> := Before}}, _NewSources, _OldSources, _AppEnvs) ->
|
||||
InitedSources = lookup(),
|
||||
{_, Source0} = find_source_by_id(Id, InitedSources),
|
||||
{Index, Source1} = find_source_by_id(BeforeId, InitedSources),
|
||||
{_, Source0} = find_source_by_type(Type, InitedSources),
|
||||
{Index, Source1} = find_source_by_type(Before, InitedSources),
|
||||
{Sources1, Sources2} = lists:split(Index, InitedSources),
|
||||
Sources3 = lists:delete(Source0, lists:droplast(Sources1))
|
||||
++ [Source0] ++ [Source1]
|
||||
|
@ -134,10 +145,10 @@ post_config_update({move, Id, #{<<"before">> := BeforeId}}, _NewSources, _OldSou
|
|||
ok = emqx_hooks:put('client.authorize', {?MODULE, authorize, [Sources3]}, -1),
|
||||
ok = emqx_authz_cache:drain_cache();
|
||||
|
||||
post_config_update({move, Id, #{<<"after">> := AfterId}}, _NewSources, _OldSources, _AppEnvs) ->
|
||||
post_config_update({move, Type, #{<<"after">> := After}}, _NewSources, _OldSources, _AppEnvs) ->
|
||||
InitedSources = lookup(),
|
||||
{_, Source} = find_source_by_id(Id, InitedSources),
|
||||
{Index, _} = find_source_by_id(AfterId, InitedSources),
|
||||
{_, Source} = find_source_by_type(Type, InitedSources),
|
||||
{Index, _} = find_source_by_type(After, InitedSources),
|
||||
{Sources1, Sources2} = lists:split(Index, InitedSources),
|
||||
Sources3 = lists:delete(Source, Sources1)
|
||||
++ [Source]
|
||||
|
@ -155,9 +166,9 @@ post_config_update({tail, Sources}, _NewSources, _OldConf, _AppEnvs) ->
|
|||
emqx_hooks:put('client.authorize', {?MODULE, authorize, [lookup() ++ InitedSources]}, -1),
|
||||
ok = emqx_authz_cache:drain_cache();
|
||||
|
||||
post_config_update({{replace_once, Id}, Source}, _NewSources, _OldConf, _AppEnvs) when is_map(Source) ->
|
||||
post_config_update({{replace_once, Type}, #{type := Type} = Source}, _NewSources, _OldConf, _AppEnvs) when is_map(Source) ->
|
||||
OldInitedSources = lookup(),
|
||||
{Index, OldSource} = find_source_by_id(Id, OldInitedSources),
|
||||
{Index, OldSource} = find_source_by_type(Type, OldInitedSources),
|
||||
case maps:get(type, OldSource, undefined) of
|
||||
undefined -> ok;
|
||||
_ ->
|
||||
|
@ -165,10 +176,19 @@ post_config_update({{replace_once, Id}, Source}, _NewSources, _OldConf, _AppEnvs
|
|||
ok = emqx_resource:remove(Id)
|
||||
end,
|
||||
{OldSources1, OldSources2 } = lists:split(Index, OldInitedSources),
|
||||
InitedSources = [init_source(R#{annotations => #{id => Id}}) || R <- check_sources([Source])],
|
||||
InitedSources = [init_source(R) || R <- check_sources([Source])],
|
||||
ok = emqx_hooks:put('client.authorize', {?MODULE, authorize, [lists:droplast(OldSources1) ++ InitedSources ++ OldSources2]}, -1),
|
||||
ok = emqx_authz_cache:drain_cache();
|
||||
|
||||
post_config_update({{delete_once, Type}, _Source}, _NewSources, _OldConf, _AppEnvs) ->
|
||||
OldInitedSources = lookup(),
|
||||
{_, OldSource} = find_source_by_type(Type, OldInitedSources),
|
||||
case OldSource of
|
||||
#{annotations := #{id := Id}} ->
|
||||
ok = emqx_resource:remove(Id);
|
||||
_ -> ok
|
||||
end,
|
||||
ok = emqx_hooks:put('client.authorize', {?MODULE, authorize, [lists:delete(OldSource, OldInitedSources)]}, -1),
|
||||
ok = emqx_authz_cache:drain_cache();
|
||||
post_config_update(_, NewSources, _OldConf, _AppEnvs) ->
|
||||
%% overwrite the entire config!
|
||||
OldInitedSources = lookup(),
|
||||
|
@ -181,48 +201,9 @@ post_config_update(_, NewSources, _OldConf, _AppEnvs) ->
|
|||
ok = emqx_authz_cache:drain_cache().
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Internal functions
|
||||
%% Initialize source
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
check_sources(RawSources) ->
|
||||
{ok, Conf} = hocon:binary(jsx:encode(#{<<"authorization">> => #{<<"sources">> => RawSources}}), #{format => richmap}),
|
||||
CheckConf = hocon_schema:check(emqx_authz_schema, Conf, #{atom_key => true}),
|
||||
#{authorization:= #{sources := Sources}} = hocon_schema:richmap_to_map(CheckConf),
|
||||
Sources.
|
||||
|
||||
find_source_by_id(Id) -> find_source_by_id(Id, lookup()).
|
||||
find_source_by_id(Id, Sources) -> find_source_by_id(Id, Sources, 1).
|
||||
find_source_by_id(_SourceId, [], _N) -> error(not_found_rule);
|
||||
find_source_by_id(SourceId, [ Source = #{annotations := #{id := Id}} | Tail], N) ->
|
||||
case SourceId =:= Id of
|
||||
true -> {N, Source};
|
||||
false -> find_source_by_id(SourceId, Tail, N + 1)
|
||||
end.
|
||||
|
||||
find_action_in_hooks() ->
|
||||
Callbacks = emqx_hooks:lookup('client.authorize'),
|
||||
[Action] = [Action || {callback,{?MODULE, authorize, _} = Action, _, _} <- Callbacks ],
|
||||
Action.
|
||||
|
||||
gen_id(Type) ->
|
||||
iolist_to_binary([io_lib:format("~s_~s",[?APP, Type]), "_", integer_to_list(erlang:system_time())]).
|
||||
|
||||
create_resource(#{type := DB,
|
||||
config := Config,
|
||||
annotations := #{id := ResourceID}}) ->
|
||||
case emqx_resource:update(ResourceID, connector_module(DB), Config, []) of
|
||||
{ok, _} -> ResourceID;
|
||||
{error, Reason} -> {error, Reason}
|
||||
end;
|
||||
create_resource(#{type := DB,
|
||||
config := Config}) ->
|
||||
ResourceID = gen_id(DB),
|
||||
case emqx_resource:create(ResourceID, connector_module(DB), Config) of
|
||||
{ok, already_created} -> ResourceID;
|
||||
{ok, _} -> ResourceID;
|
||||
{error, Reason} -> {error, Reason}
|
||||
end.
|
||||
|
||||
init_source(#{enable := true,
|
||||
type := file,
|
||||
path := Path
|
||||
|
@ -240,10 +221,7 @@ init_source(#{enable := true,
|
|||
?LOG(alert, "Failed to read ~s: ~p", [Path, Reason]),
|
||||
error(Reason)
|
||||
end,
|
||||
Source#{annotations =>
|
||||
#{id => gen_id(file),
|
||||
rules => Rules
|
||||
}};
|
||||
Source#{annotations => #{rules => Rules}};
|
||||
init_source(#{enable := true,
|
||||
type := http,
|
||||
config := #{url := Url} = Config
|
||||
|
@ -251,9 +229,7 @@ init_source(#{enable := true,
|
|||
NConfig = maps:merge(Config, #{base_url => maps:remove(query, Url)}),
|
||||
case create_resource(Source#{config := NConfig}) of
|
||||
{error, Reason} -> error({load_config_error, Reason});
|
||||
Id -> Source#{annotations =>
|
||||
#{id => Id}
|
||||
}
|
||||
Id -> Source#{annotations => #{id => Id}}
|
||||
end;
|
||||
init_source(#{enable := true,
|
||||
type := DB
|
||||
|
@ -261,9 +237,7 @@ init_source(#{enable := true,
|
|||
DB =:= mongo ->
|
||||
case create_resource(Source) of
|
||||
{error, Reason} -> error({load_config_error, Reason});
|
||||
Id -> Source#{annotations =>
|
||||
#{id => Id}
|
||||
}
|
||||
Id -> Source#{annotations => #{id => Id}}
|
||||
end;
|
||||
init_source(#{enable := true,
|
||||
type := DB,
|
||||
|
@ -323,8 +297,58 @@ do_authorize(Client, PubSub, Topic,
|
|||
Matched -> Matched
|
||||
end.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Internal function
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
check_sources(RawSources) ->
|
||||
{ok, Conf} = hocon:binary(jsx:encode(#{<<"authorization">> => #{<<"sources">> => RawSources}}), #{format => richmap}),
|
||||
CheckConf = hocon_schema:check(emqx_authz_schema, Conf, #{atom_key => true}),
|
||||
#{authorization:= #{sources := Sources}} = hocon_schema:richmap_to_map(CheckConf),
|
||||
Sources.
|
||||
|
||||
find_source_by_type(Type) -> find_source_by_type(Type, lookup()).
|
||||
find_source_by_type(Type, Sources) -> find_source_by_type(Type, Sources, 1).
|
||||
find_source_by_type(_, [], _N) -> error(not_found_rule);
|
||||
find_source_by_type(Type, [ Source = #{type := T} | Tail], N) ->
|
||||
case Type =:= T of
|
||||
true -> {N, Source};
|
||||
false -> find_source_by_type(Type, Tail, N + 1)
|
||||
end.
|
||||
|
||||
find_action_in_hooks() ->
|
||||
Callbacks = emqx_hooks:lookup('client.authorize'),
|
||||
[Action] = [Action || {callback,{?MODULE, authorize, _} = Action, _, _} <- Callbacks ],
|
||||
Action.
|
||||
|
||||
gen_id(Type) ->
|
||||
iolist_to_binary([io_lib:format("~s_~s",[?APP, Type])]).
|
||||
|
||||
create_resource(#{type := DB,
|
||||
config := Config,
|
||||
annotations := #{id := ResourceID}}) ->
|
||||
case emqx_resource:update(ResourceID, connector_module(DB), Config, []) of
|
||||
{ok, _} -> ResourceID;
|
||||
{error, Reason} -> {error, Reason}
|
||||
end;
|
||||
create_resource(#{type := DB,
|
||||
config := Config}) ->
|
||||
ResourceID = gen_id(DB),
|
||||
case emqx_resource:create(ResourceID, connector_module(DB), Config) of
|
||||
{ok, already_created} -> ResourceID;
|
||||
{ok, _} -> ResourceID;
|
||||
{error, Reason} -> {error, Reason}
|
||||
end.
|
||||
|
||||
authz_module(Type) ->
|
||||
list_to_existing_atom("emqx_authz_" ++ atom_to_list(Type)).
|
||||
|
||||
connector_module(Type) ->
|
||||
list_to_existing_atom("emqx_connector_" ++ atom_to_list(Type)).
|
||||
|
||||
atom(B) when is_binary(B) ->
|
||||
try binary_to_existing_atom(B, utf8)
|
||||
catch
|
||||
_ -> binary_to_atom(B)
|
||||
end;
|
||||
atom(A) when is_atom(A) -> A.
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
|
||||
-define(EXAMPLE_RETURNED_RULES,
|
||||
#{rules => [?EXAMPLE_RETURNED_RULE1
|
||||
#{sources => [?EXAMPLE_RETURNED_RULE1
|
||||
]
|
||||
}).
|
||||
|
||||
|
@ -40,23 +40,23 @@
|
|||
topics => [<<"#">>]}).
|
||||
|
||||
-export([ api_spec/0
|
||||
, rules/2
|
||||
, rule/2
|
||||
, move_rule/2
|
||||
, sources/2
|
||||
, source/2
|
||||
, move_source/2
|
||||
]).
|
||||
|
||||
api_spec() ->
|
||||
{[ rules_api()
|
||||
, rule_api()
|
||||
, move_rule_api()
|
||||
{[ sources_api()
|
||||
, source_api()
|
||||
, move_source_api()
|
||||
], definitions()}.
|
||||
|
||||
definitions() -> emqx_authz_api_schema:definitions().
|
||||
|
||||
rules_api() ->
|
||||
sources_api() ->
|
||||
Metadata = #{
|
||||
get => #{
|
||||
description => "List authorization rules",
|
||||
description => "List authorization sources",
|
||||
parameters => [
|
||||
#{
|
||||
name => page,
|
||||
|
@ -82,16 +82,16 @@ rules_api() ->
|
|||
'application/json' => #{
|
||||
schema => #{
|
||||
type => object,
|
||||
required => [rules],
|
||||
properties => #{rules => #{
|
||||
required => [sources],
|
||||
properties => #{sources => #{
|
||||
type => array,
|
||||
items => minirest:ref(<<"returned_rules">>)
|
||||
items => minirest:ref(<<"returned_sources">>)
|
||||
}
|
||||
}
|
||||
},
|
||||
examples => #{
|
||||
rules => #{
|
||||
summary => <<"Rules">>,
|
||||
sources => #{
|
||||
summary => <<"Sources">>,
|
||||
value => jsx:encode(?EXAMPLE_RETURNED_RULES)
|
||||
}
|
||||
}
|
||||
|
@ -101,14 +101,14 @@ rules_api() ->
|
|||
}
|
||||
},
|
||||
post => #{
|
||||
description => "Add new rule",
|
||||
description => "Add new source",
|
||||
requestBody => #{
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"rules">>),
|
||||
schema => minirest:ref(<<"sources">>),
|
||||
examples => #{
|
||||
simple_rule => #{
|
||||
summary => <<"Rules">>,
|
||||
simple_source => #{
|
||||
summary => <<"Sources">>,
|
||||
value => jsx:encode(?EXAMPLE_RULE1)
|
||||
}
|
||||
}
|
||||
|
@ -138,17 +138,17 @@ rules_api() ->
|
|||
},
|
||||
put => #{
|
||||
|
||||
description => "Update all rules",
|
||||
description => "Update all sources",
|
||||
requestBody => #{
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => #{
|
||||
type => array,
|
||||
items => minirest:ref(<<"returned_rules">>)
|
||||
items => minirest:ref(<<"returned_sources">>)
|
||||
},
|
||||
examples => #{
|
||||
rules => #{
|
||||
summary => <<"Rules">>,
|
||||
sources => #{
|
||||
summary => <<"Sources">>,
|
||||
value => jsx:encode([?EXAMPLE_RULE1])
|
||||
}
|
||||
}
|
||||
|
@ -177,15 +177,15 @@ rules_api() ->
|
|||
}
|
||||
}
|
||||
},
|
||||
{"/authorization", Metadata, rules}.
|
||||
{"/authorization", Metadata, sources}.
|
||||
|
||||
rule_api() ->
|
||||
source_api() ->
|
||||
Metadata = #{
|
||||
get => #{
|
||||
description => "List authorization rules",
|
||||
description => "List authorization sources",
|
||||
parameters => [
|
||||
#{
|
||||
name => id,
|
||||
name => type,
|
||||
in => path,
|
||||
schema => #{
|
||||
type => string
|
||||
|
@ -198,10 +198,10 @@ rule_api() ->
|
|||
description => <<"OK">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"returned_rules">>),
|
||||
schema => minirest:ref(<<"returned_sources">>),
|
||||
examples => #{
|
||||
rules => #{
|
||||
summary => <<"Rules">>,
|
||||
sources => #{
|
||||
summary => <<"Sources">>,
|
||||
value => jsx:encode(?EXAMPLE_RETURNED_RULE1)
|
||||
}
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ rule_api() ->
|
|||
summary => <<"Not Found">>,
|
||||
value => #{
|
||||
code => <<"NOT_FOUND">>,
|
||||
message => <<"rule xxx not found">>
|
||||
message => <<"source xxx not found">>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -228,10 +228,10 @@ rule_api() ->
|
|||
}
|
||||
},
|
||||
put => #{
|
||||
description => "Update rule",
|
||||
description => "Update source",
|
||||
parameters => [
|
||||
#{
|
||||
name => id,
|
||||
name => type,
|
||||
in => path,
|
||||
schema => #{
|
||||
type => string
|
||||
|
@ -242,10 +242,10 @@ rule_api() ->
|
|||
requestBody => #{
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"rules">>),
|
||||
schema => minirest:ref(<<"sources">>),
|
||||
examples => #{
|
||||
simple_rule => #{
|
||||
summary => <<"Rules">>,
|
||||
simple_source => #{
|
||||
summary => <<"Sources">>,
|
||||
value => jsx:encode(?EXAMPLE_RULE1)
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ rule_api() ->
|
|||
summary => <<"Not Found">>,
|
||||
value => #{
|
||||
code => <<"NOT_FOUND">>,
|
||||
message => <<"rule xxx not found">>
|
||||
message => <<"source xxx not found">>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ rule_api() ->
|
|||
}
|
||||
},
|
||||
delete => #{
|
||||
description => "Delete rule",
|
||||
description => "Delete source",
|
||||
parameters => [
|
||||
#{
|
||||
name => id,
|
||||
|
@ -324,15 +324,15 @@ rule_api() ->
|
|||
}
|
||||
}
|
||||
},
|
||||
{"/authorization/:id", Metadata, rule}.
|
||||
{"/authorization/:type", Metadata, source}.
|
||||
|
||||
move_rule_api() ->
|
||||
move_source_api() ->
|
||||
Metadata = #{
|
||||
post => #{
|
||||
description => "Change the order of rules",
|
||||
description => "Change the order of sources",
|
||||
parameters => [
|
||||
#{
|
||||
name => id,
|
||||
name => type,
|
||||
in => path,
|
||||
schema => #{
|
||||
type => string
|
||||
|
@ -381,15 +381,13 @@ move_rule_api() ->
|
|||
},
|
||||
<<"404">> => #{
|
||||
description => <<"Bad Request">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"error">>),
|
||||
content => #{ 'application/json' => #{ schema => minirest:ref(<<"error">>),
|
||||
examples => #{
|
||||
example1 => #{
|
||||
summary => <<"Not Found">>,
|
||||
value => #{
|
||||
code => <<"NOT_FOUND">>,
|
||||
message => <<"rule xxx not found">>
|
||||
message => <<"source xxx not found">>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -416,56 +414,54 @@ move_rule_api() ->
|
|||
}
|
||||
}
|
||||
},
|
||||
{"/authorization/:id/move", Metadata, move_rule}.
|
||||
{"/authorization/:type/move", Metadata, move_source}.
|
||||
|
||||
rules(get, #{query_string := Query}) ->
|
||||
Rules = lists:foldl(fun (#{type := _Type, enable := true, config := #{server := Server} = Config, annotations := #{id := Id}} = Rule, AccIn) ->
|
||||
NRule = case emqx_resource:health_check(Id) of
|
||||
sources(get, #{query_string := Query}) ->
|
||||
Sources = lists:foldl(fun (#{type := _Type, enable := true, config := #{server := Server} = Config, annotations := #{id := Id}} = Source, AccIn) ->
|
||||
NSource = case emqx_resource:health_check(Id) of
|
||||
ok ->
|
||||
Rule#{config => Config#{server => emqx_connector_schema_lib:ip_port_to_string(Server)},
|
||||
Source#{config => Config#{server => emqx_connector_schema_lib:ip_port_to_string(Server)},
|
||||
annotations => #{id => Id,
|
||||
status => healthy}};
|
||||
_ ->
|
||||
Rule#{config => Config#{server => emqx_connector_schema_lib:ip_port_to_string(Server)},
|
||||
Source#{config => Config#{server => emqx_connector_schema_lib:ip_port_to_string(Server)},
|
||||
annotations => #{id => Id,
|
||||
status => unhealthy}}
|
||||
end,
|
||||
lists:append(AccIn, [NRule]);
|
||||
(#{type := _Type, enable := true, annotations := #{id := Id}} = Rule, AccIn) ->
|
||||
NRule = case emqx_resource:health_check(Id) of
|
||||
lists:append(AccIn, [NSource]);
|
||||
(#{type := _Type, enable := true, annotations := #{id := Id}} = Source, AccIn) ->
|
||||
NSource = case emqx_resource:health_check(Id) of
|
||||
ok ->
|
||||
Rule#{annotations => #{id => Id,
|
||||
status => healthy}};
|
||||
Source#{annotations => #{status => healthy}};
|
||||
_ ->
|
||||
Rule#{annotations => #{id => Id,
|
||||
status => unhealthy}}
|
||||
Source#{annotations => #{status => unhealthy}}
|
||||
end,
|
||||
lists:append(AccIn, [NRule]);
|
||||
(Rule, AccIn) ->
|
||||
lists:append(AccIn, [Rule])
|
||||
lists:append(AccIn, [NSource]);
|
||||
(Source, AccIn) ->
|
||||
lists:append(AccIn, [Source])
|
||||
end, [], emqx_authz:lookup()),
|
||||
case maps:is_key(<<"page">>, Query) andalso maps:is_key(<<"limit">>, Query) of
|
||||
true ->
|
||||
Page = maps:get(<<"page">>, Query),
|
||||
Limit = maps:get(<<"limit">>, Query),
|
||||
Index = (binary_to_integer(Page) - 1) * binary_to_integer(Limit),
|
||||
{_, Rules1} = lists:split(Index, Rules),
|
||||
case binary_to_integer(Limit) < length(Rules1) of
|
||||
{_, Sources1} = lists:split(Index, Sources),
|
||||
case binary_to_integer(Limit) < length(Sources1) of
|
||||
true ->
|
||||
{Rules2, _} = lists:split(binary_to_integer(Limit), Rules1),
|
||||
{200, #{rules => Rules2}};
|
||||
false -> {200, #{rules => Rules1}}
|
||||
{Sources2, _} = lists:split(binary_to_integer(Limit), Sources1),
|
||||
{200, #{sources => Sources2}};
|
||||
false -> {200, #{sources => Sources1}}
|
||||
end;
|
||||
false -> {200, #{rules => Rules}}
|
||||
false -> {200, #{sources => Sources}}
|
||||
end;
|
||||
rules(post, #{body := RawConfig}) ->
|
||||
sources(post, #{body := RawConfig}) ->
|
||||
case emqx_authz:update(head, [RawConfig]) of
|
||||
{ok, _} -> {204};
|
||||
{error, Reason} ->
|
||||
{400, #{code => <<"BAD_REQUEST">>,
|
||||
messgae => atom_to_binary(Reason)}}
|
||||
end;
|
||||
rules(put, #{body := RawConfig}) ->
|
||||
sources(put, #{body := RawConfig}) ->
|
||||
case emqx_authz:update(replace, RawConfig) of
|
||||
{ok, _} -> {204};
|
||||
{error, Reason} ->
|
||||
|
@ -473,56 +469,57 @@ rules(put, #{body := RawConfig}) ->
|
|||
messgae => atom_to_binary(Reason)}}
|
||||
end.
|
||||
|
||||
rule(get, #{bindings := #{id := Id}}) ->
|
||||
case emqx_authz:lookup(Id) of
|
||||
source(get, #{bindings := #{type := Type}}) ->
|
||||
case emqx_authz:lookup(Type) of
|
||||
{error, Reason} -> {404, #{messgae => atom_to_binary(Reason)}};
|
||||
#{type := file} = Rule -> {200, Rule};
|
||||
#{config := #{server := Server} = Config} = Rule ->
|
||||
#{enable := false} = Source -> {200, Source};
|
||||
#{type := file} = Source -> {200, Source};
|
||||
#{config := #{server := Server,
|
||||
annotations := #{id := Id}
|
||||
} = Config} = Source ->
|
||||
case emqx_resource:health_check(Id) of
|
||||
ok ->
|
||||
{200, Rule#{config => Config#{server => emqx_connector_schema_lib:ip_port_to_string(Server)},
|
||||
annotations => #{id => Id,
|
||||
status => healthy}}};
|
||||
{200, Source#{config => Config#{server => emqx_connector_schema_lib:ip_port_to_string(Server)},
|
||||
annotations => #{status => healthy}}};
|
||||
_ ->
|
||||
{200, Rule#{config => Config#{server => emqx_connector_schema_lib:ip_port_to_string(Server)},
|
||||
annotations => #{id => Id,
|
||||
status => unhealthy}}}
|
||||
{200, Source#{config => Config#{server => emqx_connector_schema_lib:ip_port_to_string(Server)},
|
||||
annotations => #{status => unhealthy}}}
|
||||
end;
|
||||
Rule ->
|
||||
#{config := #{annotations := #{id := Id}}} = Source ->
|
||||
case emqx_resource:health_check(Id) of
|
||||
ok ->
|
||||
{200, Rule#{annotations => #{id => Id,
|
||||
status => healthy}}};
|
||||
{200, Source#{annotations => #{status => healthy}}};
|
||||
_ ->
|
||||
{200, Rule#{annotations => #{id => Id,
|
||||
status => unhealthy}}}
|
||||
{200, Source#{annotations => #{status => unhealthy}}}
|
||||
end
|
||||
end;
|
||||
rule(put, #{bindings := #{id := RuleId}, body := RawConfig}) ->
|
||||
case emqx_authz:update({replace_once, RuleId}, RawConfig) of
|
||||
source(put, #{bindings := #{type := Type}, body := RawConfig}) ->
|
||||
case emqx_authz:update({replace_once, Type}, RawConfig) of
|
||||
{ok, _} -> {204};
|
||||
{error, not_found_rule} ->
|
||||
{error, not_found_source} ->
|
||||
{404, #{code => <<"NOT_FOUND">>,
|
||||
messgae => <<"rule ", RuleId/binary, " not found">>}};
|
||||
messgae => <<"source ", Type/binary, " not found">>}};
|
||||
{error, Reason} ->
|
||||
{400, #{code => <<"BAD_REQUEST">>,
|
||||
messgae => atom_to_binary(Reason)}}
|
||||
end;
|
||||
rule(delete, #{bindings := #{id := RuleId}}) ->
|
||||
case emqx_authz:update({replace_once, RuleId}, #{}) of
|
||||
source(delete, #{bindings := #{type := Type}}) ->
|
||||
case emqx_authz:update({delete_once, Type}, #{}) of
|
||||
{ok, _} -> {204};
|
||||
{error, Reason} ->
|
||||
{400, #{code => <<"BAD_REQUEST">>,
|
||||
messgae => atom_to_binary(Reason)}}
|
||||
end.
|
||||
move_rule(post, #{bindings := #{id := RuleId}, body := Body}) ->
|
||||
#{<<"position">> := Position} = Body,
|
||||
case emqx_authz:move(RuleId, Position) of
|
||||
move_source(post, #{bindings := #{type := Type}, body := #{<<"position">> := Position}}) ->
|
||||
case emqx_authz:move(Type, Position) of
|
||||
{ok, _} -> {204};
|
||||
{error, not_found_rule} ->
|
||||
{error, not_found_source} ->
|
||||
{404, #{code => <<"NOT_FOUND">>,
|
||||
messgae => <<"rule ", RuleId/binary, " not found">>}};
|
||||
messgae => <<"source ", Type/binary, " not found">>}};
|
||||
{error, Reason} ->
|
||||
{400, #{code => <<"BAD_REQUEST">>,
|
||||
messgae => atom_to_binary(Reason)}}
|
||||
end.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -34,11 +34,11 @@ definitions() ->
|
|||
}
|
||||
}
|
||||
}
|
||||
, minirest:ref(<<"rules">>)
|
||||
, minirest:ref(<<"sources">>)
|
||||
]
|
||||
},
|
||||
Rules = #{
|
||||
oneOf => [ minirest:ref(<<"simple_rule">>)
|
||||
oneOf => [ minirest:ref(<<"simple_source">>)
|
||||
% , minirest:ref(<<"connector_redis">>)
|
||||
]
|
||||
},
|
||||
|
@ -144,9 +144,9 @@ definitions() ->
|
|||
}
|
||||
}
|
||||
},
|
||||
[ #{<<"returned_rules">> => RetruenedRules}
|
||||
, #{<<"rules">> => Rules}
|
||||
, #{<<"simple_rule">> => SimpleRule}
|
||||
[ #{<<"returned_sources">> => RetruenedRules}
|
||||
, #{<<"sources">> => Rules}
|
||||
, #{<<"simple_source">> => SimpleRule}
|
||||
, #{<<"principal">> => Principal}
|
||||
, #{<<"principal_username">> => PrincipalUsername}
|
||||
, #{<<"principal_clientid">> => PrincipalClientid}
|
||||
|
|
|
@ -61,6 +61,7 @@ init_per_testcase(_, Config) ->
|
|||
Config.
|
||||
|
||||
-define(SOURCE1, #{<<"type">> => <<"http">>,
|
||||
<<"enable">> => true,
|
||||
<<"config">> => #{
|
||||
<<"url">> => <<"https://fake.com:443/">>,
|
||||
<<"headers">> => #{},
|
||||
|
@ -68,6 +69,7 @@ init_per_testcase(_, Config) ->
|
|||
<<"request_timeout">> => 5000}
|
||||
}).
|
||||
-define(SOURCE2, #{<<"type">> => <<"mongo">>,
|
||||
<<"enable">> => true,
|
||||
<<"config">> => #{
|
||||
<<"mongo_type">> => <<"single">>,
|
||||
<<"server">> => <<"127.0.0.1:27017">>,
|
||||
|
@ -78,6 +80,7 @@ init_per_testcase(_, Config) ->
|
|||
<<"find">> => #{<<"a">> => <<"b">>}
|
||||
}).
|
||||
-define(SOURCE3, #{<<"type">> => <<"mysql">>,
|
||||
<<"enable">> => true,
|
||||
<<"config">> => #{
|
||||
<<"server">> => <<"127.0.0.1:27017">>,
|
||||
<<"pool_size">> => 1,
|
||||
|
@ -89,6 +92,7 @@ init_per_testcase(_, Config) ->
|
|||
<<"sql">> => <<"abcb">>
|
||||
}).
|
||||
-define(SOURCE4, #{<<"type">> => <<"pgsql">>,
|
||||
<<"enable">> => true,
|
||||
<<"config">> => #{
|
||||
<<"server">> => <<"127.0.0.1:27017">>,
|
||||
<<"pool_size">> => 1,
|
||||
|
@ -100,6 +104,7 @@ init_per_testcase(_, Config) ->
|
|||
<<"sql">> => <<"abcb">>
|
||||
}).
|
||||
-define(SOURCE5, #{<<"type">> => <<"redis">>,
|
||||
<<"enable">> => true,
|
||||
<<"config">> => #{
|
||||
<<"server">> => <<"127.0.0.1:27017">>,
|
||||
<<"pool_size">> => 1,
|
||||
|
@ -115,66 +120,73 @@ init_per_testcase(_, Config) ->
|
|||
%%------------------------------------------------------------------------------
|
||||
|
||||
t_update_source(_) ->
|
||||
{ok, _} = emqx_authz:update(replace, [?SOURCE2]),
|
||||
{ok, _} = emqx_authz:update(replace, [?SOURCE3]),
|
||||
{ok, _} = emqx_authz:update(head, [?SOURCE2]),
|
||||
{ok, _} = emqx_authz:update(head, [?SOURCE1]),
|
||||
{ok, _} = emqx_authz:update(tail, [?SOURCE3]),
|
||||
{ok, _} = emqx_authz:update(tail, [?SOURCE4]),
|
||||
{ok, _} = emqx_authz:update(tail, [?SOURCE5]),
|
||||
|
||||
?assertMatch([#{type := http}, #{type := mongo}, #{type := mysql}], emqx:get_config([authorization, sources], [])),
|
||||
?assertMatch([ #{type := http, enable := true}
|
||||
, #{type := mongo, enable := true}
|
||||
, #{type := mysql, enable := true}
|
||||
, #{type := pgsql, enable := true}
|
||||
, #{type := redis, enable := true}
|
||||
], emqx:get_config([authorization, sources], [])),
|
||||
|
||||
[#{annotations := #{id := Id1}, type := http},
|
||||
#{annotations := #{id := Id2}, type := mongo},
|
||||
#{annotations := #{id := Id3}, type := mysql}
|
||||
] = emqx_authz:lookup(),
|
||||
{ok, _} = emqx_authz:update({replace_once, http}, ?SOURCE1#{<<"enable">> := false}),
|
||||
{ok, _} = emqx_authz:update({replace_once, mongo}, ?SOURCE2#{<<"enable">> := false}),
|
||||
{ok, _} = emqx_authz:update({replace_once, mysql}, ?SOURCE3#{<<"enable">> := false}),
|
||||
{ok, _} = emqx_authz:update({replace_once, pgsql}, ?SOURCE4#{<<"enable">> := false}),
|
||||
{ok, _} = emqx_authz:update({replace_once, redis}, ?SOURCE5#{<<"enable">> := false}),
|
||||
|
||||
{ok, _} = emqx_authz:update({replace_once, Id1}, ?SOURCE5),
|
||||
{ok, _} = emqx_authz:update({replace_once, Id3}, ?SOURCE4),
|
||||
?assertMatch([#{type := redis}, #{type := mongo}, #{type := pgsql}], emqx:get_config([authorization, sources], [])),
|
||||
|
||||
[#{annotations := #{id := Id1}, type := redis},
|
||||
#{annotations := #{id := Id2}, type := mongo},
|
||||
#{annotations := #{id := Id3}, type := pgsql}
|
||||
] = emqx_authz:lookup(),
|
||||
?assertMatch([ #{type := http, enable := false}
|
||||
, #{type := mongo, enable := false}
|
||||
, #{type := mysql, enable := false}
|
||||
, #{type := pgsql, enable := false}
|
||||
, #{type := redis, enable := false}
|
||||
], emqx:get_config([authorization, sources], [])),
|
||||
|
||||
{ok, _} = emqx_authz:update(replace, []).
|
||||
|
||||
t_move_source(_) ->
|
||||
{ok, _} = emqx_authz:update(replace, [?SOURCE1, ?SOURCE2, ?SOURCE3, ?SOURCE4, ?SOURCE5]),
|
||||
[#{annotations := #{id := Id1}},
|
||||
#{annotations := #{id := Id2}},
|
||||
#{annotations := #{id := Id3}},
|
||||
#{annotations := #{id := Id4}},
|
||||
#{annotations := #{id := Id5}}
|
||||
] = emqx_authz:lookup(),
|
||||
|
||||
{ok, _} = emqx_authz:move(Id4, <<"top">>),
|
||||
?assertMatch([#{annotations := #{id := Id4}},
|
||||
#{annotations := #{id := Id1}},
|
||||
#{annotations := #{id := Id2}},
|
||||
#{annotations := #{id := Id3}},
|
||||
#{annotations := #{id := Id5}}
|
||||
?assertMatch([ #{type := http}
|
||||
, #{type := mongo}
|
||||
, #{type := mysql}
|
||||
, #{type := pgsql}
|
||||
, #{type := redis}
|
||||
], emqx_authz:lookup()),
|
||||
|
||||
{ok, _} = emqx_authz:move(Id1, <<"bottom">>),
|
||||
?assertMatch([#{annotations := #{id := Id4}},
|
||||
#{annotations := #{id := Id2}},
|
||||
#{annotations := #{id := Id3}},
|
||||
#{annotations := #{id := Id5}},
|
||||
#{annotations := #{id := Id1}}
|
||||
{ok, _} = emqx_authz:move(pgsql, <<"top">>),
|
||||
?assertMatch([ #{type := pgsql}
|
||||
, #{type := http}
|
||||
, #{type := mongo}
|
||||
, #{type := mysql}
|
||||
, #{type := redis}
|
||||
], emqx_authz:lookup()),
|
||||
|
||||
{ok, _} = emqx_authz:move(Id3, #{<<"before">> => Id4}),
|
||||
?assertMatch([#{annotations := #{id := Id3}},
|
||||
#{annotations := #{id := Id4}},
|
||||
#{annotations := #{id := Id2}},
|
||||
#{annotations := #{id := Id5}},
|
||||
#{annotations := #{id := Id1}}
|
||||
{ok, _} = emqx_authz:move(http, <<"bottom">>),
|
||||
?assertMatch([ #{type := pgsql}
|
||||
, #{type := mongo}
|
||||
, #{type := mysql}
|
||||
, #{type := redis}
|
||||
, #{type := http}
|
||||
], emqx_authz:lookup()),
|
||||
|
||||
{ok, _} = emqx_authz:move(Id2, #{<<"after">> => Id1}),
|
||||
?assertMatch([#{annotations := #{id := Id3}},
|
||||
#{annotations := #{id := Id4}},
|
||||
#{annotations := #{id := Id5}},
|
||||
#{annotations := #{id := Id1}},
|
||||
#{annotations := #{id := Id2}}
|
||||
{ok, _} = emqx_authz:move(mysql, #{<<"before">> => pgsql}),
|
||||
?assertMatch([ #{type := mysql}
|
||||
, #{type := pgsql}
|
||||
, #{type := mongo}
|
||||
, #{type := redis}
|
||||
, #{type := http}
|
||||
], emqx_authz:lookup()),
|
||||
|
||||
{ok, _} = emqx_authz:move(mongo, #{<<"after">> => http}),
|
||||
?assertMatch([ #{type := mysql}
|
||||
, #{type := pgsql}
|
||||
, #{type := redis}
|
||||
, #{type := http}
|
||||
, #{type := mongo}
|
||||
], emqx_authz:lookup()),
|
||||
|
||||
ok.
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
-define(BASE_PATH, "api").
|
||||
|
||||
-define(SOURCE1, #{<<"type">> => <<"http">>,
|
||||
<<"enable">> => true,
|
||||
<<"config">> => #{
|
||||
<<"url">> => <<"https://fake.com:443/">>,
|
||||
<<"headers">> => #{},
|
||||
|
@ -45,6 +46,7 @@
|
|||
<<"request_timeout">> => 5000}
|
||||
}).
|
||||
-define(SOURCE2, #{<<"type">> => <<"mongo">>,
|
||||
<<"enable">> => true,
|
||||
<<"config">> => #{
|
||||
<<"mongo_type">> => <<"single">>,
|
||||
<<"server">> => <<"127.0.0.1:27017">>,
|
||||
|
@ -55,6 +57,7 @@
|
|||
<<"find">> => #{<<"a">> => <<"b">>}
|
||||
}).
|
||||
-define(SOURCE3, #{<<"type">> => <<"mysql">>,
|
||||
<<"enable">> => true,
|
||||
<<"config">> => #{
|
||||
<<"server">> => <<"127.0.0.1:27017">>,
|
||||
<<"pool_size">> => 1,
|
||||
|
@ -66,6 +69,7 @@
|
|||
<<"sql">> => <<"abcb">>
|
||||
}).
|
||||
-define(SOURCE4, #{<<"type">> => <<"pgsql">>,
|
||||
<<"enable">> => true,
|
||||
<<"config">> => #{
|
||||
<<"server">> => <<"127.0.0.1:27017">>,
|
||||
<<"pool_size">> => 1,
|
||||
|
@ -77,6 +81,7 @@
|
|||
<<"sql">> => <<"abcb">>
|
||||
}).
|
||||
-define(SOURCE5, #{<<"type">> => <<"redis">>,
|
||||
<<"enable">> => true,
|
||||
<<"config">> => #{
|
||||
<<"server">> => <<"127.0.0.1:27017">>,
|
||||
<<"pool_size">> => 1,
|
||||
|
@ -134,7 +139,7 @@ set_special_configs(emqx_dashboard) ->
|
|||
emqx_config:put([emqx_dashboard], Config),
|
||||
ok;
|
||||
set_special_configs(emqx_authz) ->
|
||||
emqx_config:put([authorization], #{rules => []}),
|
||||
emqx_config:put([authorization], #{sources => []}),
|
||||
ok;
|
||||
set_special_configs(_App) ->
|
||||
ok.
|
||||
|
@ -145,89 +150,86 @@ set_special_configs(_App) ->
|
|||
|
||||
t_api(_) ->
|
||||
{ok, 200, Result1} = request(get, uri(["authorization"]), []),
|
||||
?assertEqual([], get_rules(Result1)),
|
||||
?assertEqual([], get_sources(Result1)),
|
||||
|
||||
lists:foreach(fun(_) ->
|
||||
{ok, 204, _} = request(post, uri(["authorization"]), ?SOURCE1)
|
||||
end, lists:seq(1, 20)),
|
||||
{ok, 200, Result2} = request(get, uri(["authorization"]), []),
|
||||
?assertEqual(20, length(get_rules(Result2))),
|
||||
?assertEqual(20, length(get_sources(Result2))),
|
||||
|
||||
lists:foreach(fun(Page) ->
|
||||
Query = "?page=" ++ integer_to_list(Page) ++ "&&limit=10",
|
||||
Url = uri(["authorization" ++ Query]),
|
||||
{ok, 200, Result} = request(get, Url, []),
|
||||
?assertEqual(10, length(get_rules(Result)))
|
||||
?assertEqual(10, length(get_sources(Result)))
|
||||
end, lists:seq(1, 2)),
|
||||
|
||||
{ok, 204, _} = request(put, uri(["authorization"]), [?SOURCE1, ?SOURCE2, ?SOURCE3, ?SOURCE4]),
|
||||
|
||||
{ok, 200, Result3} = request(get, uri(["authorization"]), []),
|
||||
Rules = get_rules(Result3),
|
||||
?assertEqual(4, length(Rules)),
|
||||
Sources = get_sources(Result3),
|
||||
?assertMatch([ #{<<"type">> := <<"http">>}
|
||||
, #{<<"type">> := <<"mongo">>}
|
||||
, #{<<"type">> := <<"mysql">>}
|
||||
, #{<<"type">> := <<"pgsql">>}
|
||||
], Rules),
|
||||
], Sources),
|
||||
|
||||
#{<<"annotations">> := #{<<"id">> := Id}} = lists:nth(2, Rules),
|
||||
{ok, 204, _} = request(put, uri(["authorization", "http"]), ?SOURCE1#{<<"enable">> := false}),
|
||||
|
||||
{ok, 204, _} = request(put, uri(["authorization", binary_to_list(Id)]), ?SOURCE5),
|
||||
{ok, 200, Result4} = request(get, uri(["authorization", "http"]), []),
|
||||
?assertMatch(#{<<"type">> := <<"http">>, <<"enable">> := false}, jsx:decode(Result4)),
|
||||
|
||||
{ok, 200, Result4} = request(get, uri(["authorization", binary_to_list(Id)]), []),
|
||||
?assertMatch(#{<<"type">> := <<"redis">>}, jsx:decode(Result4)),
|
||||
|
||||
lists:foreach(fun(#{<<"annotations">> := #{<<"id">> := Id0}}) ->
|
||||
{ok, 204, _} = request(delete, uri(["authorization", binary_to_list(Id0)]), [])
|
||||
end, Rules),
|
||||
lists:foreach(fun(#{<<"type">> := Type}) ->
|
||||
{ok, 204, _} = request(delete, uri(["authorization", binary_to_list(Type)]), [])
|
||||
end, Sources),
|
||||
{ok, 200, Result5} = request(get, uri(["authorization"]), []),
|
||||
?assertEqual([], get_rules(Result5)),
|
||||
?assertEqual([], get_sources(Result5)),
|
||||
ok.
|
||||
|
||||
t_move_rule(_) ->
|
||||
t_move_source(_) ->
|
||||
{ok, _} = emqx_authz:update(replace, [?SOURCE1, ?SOURCE2, ?SOURCE3, ?SOURCE4, ?SOURCE5]),
|
||||
[#{annotations := #{id := Id1}},
|
||||
#{annotations := #{id := Id2}},
|
||||
#{annotations := #{id := Id3}},
|
||||
#{annotations := #{id := Id4}},
|
||||
#{annotations := #{id := Id5}}
|
||||
] = emqx_authz:lookup(),
|
||||
?assertMatch([ #{type := http}
|
||||
, #{type := mongo}
|
||||
, #{type := mysql}
|
||||
, #{type := pgsql}
|
||||
, #{type := redis}
|
||||
], emqx_authz:lookup()),
|
||||
|
||||
{ok, 204, _} = request(post, uri(["authorization", Id4, "move"]),
|
||||
{ok, 204, _} = request(post, uri(["authorization", "pgsql", "move"]),
|
||||
#{<<"position">> => <<"top">>}),
|
||||
?assertMatch([#{annotations := #{id := Id4}},
|
||||
#{annotations := #{id := Id1}},
|
||||
#{annotations := #{id := Id2}},
|
||||
#{annotations := #{id := Id3}},
|
||||
#{annotations := #{id := Id5}}
|
||||
?assertMatch([ #{type := pgsql}
|
||||
, #{type := http}
|
||||
, #{type := mongo}
|
||||
, #{type := mysql}
|
||||
, #{type := redis}
|
||||
], emqx_authz:lookup()),
|
||||
|
||||
{ok, 204, _} = request(post, uri(["authorization", Id1, "move"]),
|
||||
{ok, 204, _} = request(post, uri(["authorization", "http", "move"]),
|
||||
#{<<"position">> => <<"bottom">>}),
|
||||
?assertMatch([#{annotations := #{id := Id4}},
|
||||
#{annotations := #{id := Id2}},
|
||||
#{annotations := #{id := Id3}},
|
||||
#{annotations := #{id := Id5}},
|
||||
#{annotations := #{id := Id1}}
|
||||
?assertMatch([ #{type := pgsql}
|
||||
, #{type := mongo}
|
||||
, #{type := mysql}
|
||||
, #{type := redis}
|
||||
, #{type := http}
|
||||
], emqx_authz:lookup()),
|
||||
|
||||
{ok, 204, _} = request(post, uri(["authorization", Id3, "move"]),
|
||||
#{<<"position">> => #{<<"before">> => Id4}}),
|
||||
?assertMatch([#{annotations := #{id := Id3}},
|
||||
#{annotations := #{id := Id4}},
|
||||
#{annotations := #{id := Id2}},
|
||||
#{annotations := #{id := Id5}},
|
||||
#{annotations := #{id := Id1}}
|
||||
{ok, 204, _} = request(post, uri(["authorization", "mysql", "move"]),
|
||||
#{<<"position">> => #{<<"before">> => <<"pgsql">>}}),
|
||||
?assertMatch([ #{type := mysql}
|
||||
, #{type := pgsql}
|
||||
, #{type := mongo}
|
||||
, #{type := redis}
|
||||
, #{type := http}
|
||||
], emqx_authz:lookup()),
|
||||
|
||||
{ok, 204, _} = request(post, uri(["authorization", Id2, "move"]),
|
||||
#{<<"position">> => #{<<"after">> => Id1}}),
|
||||
?assertMatch([#{annotations := #{id := Id3}},
|
||||
#{annotations := #{id := Id4}},
|
||||
#{annotations := #{id := Id5}},
|
||||
#{annotations := #{id := Id1}},
|
||||
#{annotations := #{id := Id2}}
|
||||
{ok, 204, _} = request(post, uri(["authorization", "mongo", "move"]),
|
||||
#{<<"position">> => #{<<"after">> => <<"http">>}}),
|
||||
?assertMatch([ #{type := mysql}
|
||||
, #{type := pgsql}
|
||||
, #{type := redis}
|
||||
, #{type := http}
|
||||
, #{type := mongo}
|
||||
], emqx_authz:lookup()),
|
||||
|
||||
ok.
|
||||
|
@ -256,8 +258,8 @@ uri(Parts) when is_list(Parts) ->
|
|||
NParts = [E || E <- Parts],
|
||||
?HOST ++ filename:join([?BASE_PATH, ?API_VERSION | NParts]).
|
||||
|
||||
get_rules(Result) ->
|
||||
maps:get(<<"rules">>, jsx:decode(Result), []).
|
||||
get_sources(Result) ->
|
||||
maps:get(<<"sources">>, jsx:decode(Result), []).
|
||||
|
||||
auth_header_() ->
|
||||
Username = <<"admin">>,
|
||||
|
|
Loading…
Reference in New Issue