feat(authz mnesia api): post accept array data

This commit is contained in:
zhanghongtong 2021-09-23 10:06:05 +08:00
parent 2dc3b51675
commit 1a02e0cfd1
2 changed files with 43 additions and 77 deletions

View File

@ -210,15 +210,18 @@ records_api() ->
requestBody => #{ requestBody => #{
content => #{ content => #{
'application/json' => #{ 'application/json' => #{
schema => minirest:ref(<<"record">>), schema => #{
type => array,
items => minirest:ref(<<"record">>)
},
examples => #{ examples => #{
username => #{ username => #{
summary => <<"Username">>, summary => <<"Username">>,
value => jsx:encode(?EXAMPLE_USERNAME) value => jsx:encode([?EXAMPLE_USERNAME])
}, },
clientid => #{ clientid => #{
summary => <<"Clientid">>, summary => <<"Clientid">>,
value => jsx:encode(?EXAMPLE_CLIENTID) value => jsx:encode([?EXAMPLE_CLIENTID])
} }
} }
} }
@ -421,41 +424,30 @@ records(get, #{bindings := #{type := <<"all">>}}) ->
} || {Permission, Action, Topic} <- Rules] } || {Permission, Action, Topic} <- Rules]
} || [{rules, Rules}] <- ets:select(?ACL_TABLE, MatchSpec)]}; } || [{rules, Rules}] <- ets:select(?ACL_TABLE, MatchSpec)]};
records(post, #{bindings := #{type := <<"username">>}, records(post, #{bindings := #{type := <<"username">>},
body := #{<<"username">> := Username, <<"rules">> := Rules}}) -> body := Body}) when is_list(Body) ->
Record = #emqx_acl{ lists:foreach(fun(#{<<"username">> := Username, <<"rules">> := Rules}) ->
who = {username, Username}, ekka_mnesia:dirty_write(#emqx_acl{
rules = format_rules(Rules) who = {username, Username},
}, rules = format_rules(Rules)
case ret(mnesia:transaction(fun insert/1, [Record])) of })
ok -> {204}; end, Body),
{error, Reason} -> {204};
{400, #{code => <<"BAD_REQUEST">>,
message => atom_to_binary(Reason)}}
end;
records(post, #{bindings := #{type := <<"clientid">>}, records(post, #{bindings := #{type := <<"clientid">>},
body := #{<<"clientid">> := Clientid, <<"rules">> := Rules}}) -> body := Body}) when is_list(Body) ->
Record = #emqx_acl{ lists:foreach(fun(#{<<"clientid">> := Clientid, <<"rules">> := Rules}) ->
who = {clientid, Clientid}, ekka_mnesia:dirty_write(#emqx_acl{
rules = format_rules(Rules) who = {clientid, Clientid},
}, rules = format_rules(Rules)
case ret(mnesia:transaction(fun insert/1, [Record])) of })
ok -> {204}; end, Body),
{error, Reason} -> {204};
{400, #{code => <<"BAD_REQUEST">>,
message => atom_to_binary(Reason)}}
end;
records(put, #{bindings := #{type := <<"all">>}, records(put, #{bindings := #{type := <<"all">>},
body := #{<<"rules">> := Rules}}) -> body := #{<<"rules">> := Rules}}) ->
Record = #emqx_acl{ ekka_mnesia:dirty_write(#emqx_acl{
who = all, who = all,
rules = format_rules(Rules) rules = format_rules(Rules)
}, }),
case ret(mnesia:transaction(fun ekka_mnesia:dirty_write/1, [Record])) of {204}.
ok -> {204};
{error, Reason} ->
{400, #{code => <<"BAD_REQUEST">>,
message => atom_to_binary(Reason)}}
end.
record(get, #{bindings := #{type := <<"username">>, key := Key}}) -> record(get, #{bindings := #{type := <<"username">>, key := Key}}) ->
case mnesia:dirty_read(?ACL_TABLE, {username, Key}) of case mnesia:dirty_read(?ACL_TABLE, {username, Key}) of
@ -481,34 +473,24 @@ record(get, #{bindings := #{type := <<"clientid">>, key := Key}}) ->
end; end;
record(put, #{bindings := #{type := <<"username">>, key := Username}, record(put, #{bindings := #{type := <<"username">>, key := Username},
body := #{<<"username">> := Username, <<"rules">> := Rules}}) -> body := #{<<"username">> := Username, <<"rules">> := Rules}}) ->
case ret(mnesia:transaction(fun update/2, [{username, Username}, format_rules(Rules)])) of ekka_mnesia:dirty_write(#emqx_acl{
ok -> {204}; who = {username, Username},
{error, Reason} -> rules = format_rules(Rules)
{400, #{code => <<"BAD_REQUEST">>, }),
message => atom_to_binary(Reason)}} {204};
end;
record(put, #{bindings := #{type := <<"clientid">>, key := Clientid}, record(put, #{bindings := #{type := <<"clientid">>, key := Clientid},
body := #{<<"clientid">> := Clientid, <<"rules">> := Rules}}) -> body := #{<<"clientid">> := Clientid, <<"rules">> := Rules}}) ->
case ret(mnesia:transaction(fun update/2, [{clientid, Clientid}, format_rules(Rules)])) of ekka_mnesia:dirty_write(#emqx_acl{
ok -> {204}; who = {clientid, Clientid},
{error, Reason} -> rules = format_rules(Rules)
{400, #{code => <<"BAD_REQUEST">>, }),
message => atom_to_binary(Reason)}} {204};
end;
record(delete, #{bindings := #{type := <<"username">>, key := Key}}) -> record(delete, #{bindings := #{type := <<"username">>, key := Key}}) ->
case ret(mnesia:transaction(fun ekka_mnesia:dirty_delete/1, [{?ACL_TABLE, {username, Key}}])) of ekka_mnesia:dirty_delete({?ACL_TABLE, {username, Key}}),
ok -> {204}; {204};
{error, Reason} ->
{400, #{code => <<"BAD_REQUEST">>,
message => atom_to_binary(Reason)}}
end;
record(delete, #{bindings := #{type := <<"clientid">>, key := Key}}) -> record(delete, #{bindings := #{type := <<"clientid">>, key := Key}}) ->
case ret(mnesia:transaction(fun ekka_mnesia:dirty_delete/1, [{?ACL_TABLE, {clientid, Key}}])) of ekka_mnesia:dirty_delete({?ACL_TABLE, {clientid, Key}}),
ok -> {204}; {204}.
{error, Reason} ->
{400, #{code => <<"BAD_REQUEST">>,
message => atom_to_binary(Reason)}}
end.
format_rules(Rules) when is_list(Rules) -> format_rules(Rules) when is_list(Rules) ->
lists:foldl(fun(#{<<"topic">> := Topic, lists:foldl(fun(#{<<"topic">> := Topic,
@ -525,19 +507,3 @@ atom(B) when is_binary(B) ->
_ -> binary_to_atom(B) _ -> binary_to_atom(B)
end; end;
atom(A) when is_atom(A) -> A. atom(A) when is_atom(A) -> A.
insert(Record = #emqx_acl{who = Who}) ->
case mnesia:read(?ACL_TABLE, Who) of
[] -> ekka_mnesia:dirty_write(Record);
[_|_] -> mnesia:abort(existed)
end.
update(Who, Rules) ->
case mnesia:read(?ACL_TABLE, Who) of
[#emqx_acl{} = Record] ->
ekka_mnesia:dirty_write(Record#emqx_acl{rules = Rules});
[] -> mnesia:abort(noexisted)
end.
ret({atomic, ok}) -> ok;
ret({aborted, Error}) -> {error, Error}.

View File

@ -134,7 +134,7 @@ set_special_configs(_App) ->
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------
t_api(_) -> t_api(_) ->
{ok, 204, _} = request(post, uri(["authorization", "sources", "built-in-database", "username"]), ?EXAMPLE_USERNAME), {ok, 204, _} = request(post, uri(["authorization", "sources", "built-in-database", "username"]), [?EXAMPLE_USERNAME]),
{ok, 200, Request1} = request(get, uri(["authorization", "sources", "built-in-database", "username"]), []), {ok, 200, Request1} = request(get, uri(["authorization", "sources", "built-in-database", "username"]), []),
{ok, 200, Request2} = request(get, uri(["authorization", "sources", "built-in-database", "username", "user1"]), []), {ok, 200, Request2} = request(get, uri(["authorization", "sources", "built-in-database", "username", "user1"]), []),
[#{<<"username">> := <<"user1">>, <<"rules">> := Rules1}] = jsx:decode(Request1), [#{<<"username">> := <<"user1">>, <<"rules">> := Rules1}] = jsx:decode(Request1),
@ -149,7 +149,7 @@ t_api(_) ->
{ok, 204, _} = request(delete, uri(["authorization", "sources", "built-in-database", "username", "user1"]), []), {ok, 204, _} = request(delete, uri(["authorization", "sources", "built-in-database", "username", "user1"]), []),
{ok, 404, _} = request(get, uri(["authorization", "sources", "built-in-database", "username", "user1"]), []), {ok, 404, _} = request(get, uri(["authorization", "sources", "built-in-database", "username", "user1"]), []),
{ok, 204, _} = request(post, uri(["authorization", "sources", "built-in-database", "clientid"]), ?EXAMPLE_CLIENTID), {ok, 204, _} = request(post, uri(["authorization", "sources", "built-in-database", "clientid"]), [?EXAMPLE_CLIENTID]),
{ok, 200, Request4} = request(get, uri(["authorization", "sources", "built-in-database", "clientid"]), []), {ok, 200, Request4} = request(get, uri(["authorization", "sources", "built-in-database", "clientid"]), []),
{ok, 200, Request5} = request(get, uri(["authorization", "sources", "built-in-database", "clientid", "client1"]), []), {ok, 200, Request5} = request(get, uri(["authorization", "sources", "built-in-database", "clientid", "client1"]), []),
[#{<<"clientid">> := <<"client1">>, <<"rules">> := Rules3}] = jsx:decode(Request4), [#{<<"clientid">> := <<"client1">>, <<"rules">> := Rules3}] = jsx:decode(Request4),