chore(authz): use ekka_mnesia instead of mnesia
This commit is contained in:
parent
b583509976
commit
2dc3b51675
|
@ -72,14 +72,14 @@
|
||||||
|
|
||||||
-export([ api_spec/0
|
-export([ api_spec/0
|
||||||
, purge/2
|
, purge/2
|
||||||
, tickets/2
|
, records/2
|
||||||
, ticket/2
|
, record/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
api_spec() ->
|
api_spec() ->
|
||||||
{[ purge_api()
|
{[ purge_api()
|
||||||
, tickets_api()
|
, records_api()
|
||||||
, ticket_api()
|
, record_api()
|
||||||
], definitions()}.
|
], definitions()}.
|
||||||
|
|
||||||
definitions() ->
|
definitions() ->
|
||||||
|
@ -106,7 +106,7 @@ definitions() ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Ticket = #{
|
Record = #{
|
||||||
oneOf => [ #{type => object,
|
oneOf => [ #{type => object,
|
||||||
required => [username, rules],
|
required => [username, rules],
|
||||||
properties => #{
|
properties => #{
|
||||||
|
@ -136,13 +136,13 @@ definitions() ->
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
[ #{<<"rules">> => Rules}
|
[ #{<<"rules">> => Rules}
|
||||||
, #{<<"ticket">> => Ticket}
|
, #{<<"record">> => Record}
|
||||||
].
|
].
|
||||||
|
|
||||||
purge_api() ->
|
purge_api() ->
|
||||||
Metadata = #{
|
Metadata = #{
|
||||||
delete => #{
|
delete => #{
|
||||||
description => "Purge all tickets",
|
description => "Purge all records",
|
||||||
responses => #{
|
responses => #{
|
||||||
<<"204">> => #{description => <<"No Content">>},
|
<<"204">> => #{description => <<"No Content">>},
|
||||||
<<"400">> => emqx_mgmt_util:bad_request()
|
<<"400">> => emqx_mgmt_util:bad_request()
|
||||||
|
@ -151,10 +151,10 @@ purge_api() ->
|
||||||
},
|
},
|
||||||
{"/authorization/sources/built-in-database/purge-all", Metadata, purge}.
|
{"/authorization/sources/built-in-database/purge-all", Metadata, purge}.
|
||||||
|
|
||||||
tickets_api() ->
|
records_api() ->
|
||||||
Metadata = #{
|
Metadata = #{
|
||||||
get => #{
|
get => #{
|
||||||
description => "List tickets",
|
description => "List records",
|
||||||
parameters => [
|
parameters => [
|
||||||
#{
|
#{
|
||||||
name => type,
|
name => type,
|
||||||
|
@ -173,7 +173,7 @@ tickets_api() ->
|
||||||
'application/json' => #{
|
'application/json' => #{
|
||||||
schema => #{
|
schema => #{
|
||||||
type => array,
|
type => array,
|
||||||
items => minirest:ref(<<"ticket">>)
|
items => minirest:ref(<<"record">>)
|
||||||
},
|
},
|
||||||
examples => #{
|
examples => #{
|
||||||
username => #{
|
username => #{
|
||||||
|
@ -195,7 +195,7 @@ tickets_api() ->
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
post => #{
|
post => #{
|
||||||
description => "Add new tickets",
|
description => "Add new records",
|
||||||
parameters => [
|
parameters => [
|
||||||
#{
|
#{
|
||||||
name => type,
|
name => type,
|
||||||
|
@ -210,7 +210,7 @@ tickets_api() ->
|
||||||
requestBody => #{
|
requestBody => #{
|
||||||
content => #{
|
content => #{
|
||||||
'application/json' => #{
|
'application/json' => #{
|
||||||
schema => minirest:ref(<<"ticket">>),
|
schema => minirest:ref(<<"record">>),
|
||||||
examples => #{
|
examples => #{
|
||||||
username => #{
|
username => #{
|
||||||
summary => <<"Username">>,
|
summary => <<"Username">>,
|
||||||
|
@ -245,7 +245,7 @@ tickets_api() ->
|
||||||
requestBody => #{
|
requestBody => #{
|
||||||
content => #{
|
content => #{
|
||||||
'application/json' => #{
|
'application/json' => #{
|
||||||
schema => minirest:ref(<<"ticket">>),
|
schema => minirest:ref(<<"record">>),
|
||||||
examples => #{
|
examples => #{
|
||||||
all => #{
|
all => #{
|
||||||
summary => <<"All">>,
|
summary => <<"All">>,
|
||||||
|
@ -261,12 +261,12 @@ tickets_api() ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{"/authorization/sources/built-in-database/:type", Metadata, tickets}.
|
{"/authorization/sources/built-in-database/:type", Metadata, records}.
|
||||||
|
|
||||||
ticket_api() ->
|
record_api() ->
|
||||||
Metadata = #{
|
Metadata = #{
|
||||||
get => #{
|
get => #{
|
||||||
description => "Get ticket info",
|
description => "Get record info",
|
||||||
parameters => [
|
parameters => [
|
||||||
#{
|
#{
|
||||||
name => type,
|
name => type,
|
||||||
|
@ -291,7 +291,7 @@ ticket_api() ->
|
||||||
description => <<"OK">>,
|
description => <<"OK">>,
|
||||||
content => #{
|
content => #{
|
||||||
'application/json' => #{
|
'application/json' => #{
|
||||||
schema => minirest:ref(<<"ticket">>),
|
schema => minirest:ref(<<"record">>),
|
||||||
examples => #{
|
examples => #{
|
||||||
username => #{
|
username => #{
|
||||||
summary => <<"Username">>,
|
summary => <<"Username">>,
|
||||||
|
@ -313,7 +313,7 @@ ticket_api() ->
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
put => #{
|
put => #{
|
||||||
description => "Update one ticket",
|
description => "Update one record",
|
||||||
parameters => [
|
parameters => [
|
||||||
#{
|
#{
|
||||||
name => type,
|
name => type,
|
||||||
|
@ -336,7 +336,7 @@ ticket_api() ->
|
||||||
requestBody => #{
|
requestBody => #{
|
||||||
content => #{
|
content => #{
|
||||||
'application/json' => #{
|
'application/json' => #{
|
||||||
schema => minirest:ref(<<"ticket">>),
|
schema => minirest:ref(<<"record">>),
|
||||||
examples => #{
|
examples => #{
|
||||||
username => #{
|
username => #{
|
||||||
summary => <<"Username">>,
|
summary => <<"Username">>,
|
||||||
|
@ -356,7 +356,7 @@ ticket_api() ->
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
delete => #{
|
delete => #{
|
||||||
description => "Delete one ticket",
|
description => "Delete one record",
|
||||||
parameters => [
|
parameters => [
|
||||||
#{
|
#{
|
||||||
name => type,
|
name => type,
|
||||||
|
@ -382,13 +382,13 @@ ticket_api() ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{"/authorization/sources/built-in-database/:type/:key", Metadata, ticket}.
|
{"/authorization/sources/built-in-database/:type/:key", Metadata, record}.
|
||||||
|
|
||||||
purge(delete, _) ->
|
purge(delete, _) ->
|
||||||
[ mnesia:dirty_delete(?ACL_TABLE, K) || K <- mnesia:dirty_all_keys(?ACL_TABLE)],
|
[ ekka_mnesia:dirty_delete(?ACL_TABLE, K) || K <- mnesia:dirty_all_keys(?ACL_TABLE)],
|
||||||
{204}.
|
{204}.
|
||||||
|
|
||||||
tickets(get, #{bindings := #{type := <<"username">>}}) ->
|
records(get, #{bindings := #{type := <<"username">>}}) ->
|
||||||
MatchSpec = ets:fun2ms(
|
MatchSpec = ets:fun2ms(
|
||||||
fun({?ACL_TABLE, {username, Username}, Rules}) ->
|
fun({?ACL_TABLE, {username, Username}, Rules}) ->
|
||||||
[{username, Username}, {rules, Rules}]
|
[{username, Username}, {rules, Rules}]
|
||||||
|
@ -399,7 +399,7 @@ tickets(get, #{bindings := #{type := <<"username">>}}) ->
|
||||||
permission => Permission
|
permission => Permission
|
||||||
} || {Permission, Action, Topic} <- Rules]
|
} || {Permission, Action, Topic} <- Rules]
|
||||||
} || [{username, Username}, {rules, Rules}] <- ets:select(?ACL_TABLE, MatchSpec)]};
|
} || [{username, Username}, {rules, Rules}] <- ets:select(?ACL_TABLE, MatchSpec)]};
|
||||||
tickets(get, #{bindings := #{type := <<"clientid">>}}) ->
|
records(get, #{bindings := #{type := <<"clientid">>}}) ->
|
||||||
MatchSpec = ets:fun2ms(
|
MatchSpec = ets:fun2ms(
|
||||||
fun({?ACL_TABLE, {clientid, Clientid}, Rules}) ->
|
fun({?ACL_TABLE, {clientid, Clientid}, Rules}) ->
|
||||||
[{clientid, Clientid}, {rules, Rules}]
|
[{clientid, Clientid}, {rules, Rules}]
|
||||||
|
@ -410,7 +410,7 @@ tickets(get, #{bindings := #{type := <<"clientid">>}}) ->
|
||||||
permission => Permission
|
permission => Permission
|
||||||
} || {Permission, Action, Topic} <- Rules]
|
} || {Permission, Action, Topic} <- Rules]
|
||||||
} || [{clientid, Clientid}, {rules, Rules}] <- ets:select(?ACL_TABLE, MatchSpec)]};
|
} || [{clientid, Clientid}, {rules, Rules}] <- ets:select(?ACL_TABLE, MatchSpec)]};
|
||||||
tickets(get, #{bindings := #{type := <<"all">>}}) ->
|
records(get, #{bindings := #{type := <<"all">>}}) ->
|
||||||
MatchSpec = ets:fun2ms(
|
MatchSpec = ets:fun2ms(
|
||||||
fun({?ACL_TABLE, all, Rules}) ->
|
fun({?ACL_TABLE, all, Rules}) ->
|
||||||
[{rules, Rules}]
|
[{rules, Rules}]
|
||||||
|
@ -420,44 +420,44 @@ tickets(get, #{bindings := #{type := <<"all">>}}) ->
|
||||||
permission => Permission
|
permission => Permission
|
||||||
} || {Permission, Action, Topic} <- Rules]
|
} || {Permission, Action, Topic} <- Rules]
|
||||||
} || [{rules, Rules}] <- ets:select(?ACL_TABLE, MatchSpec)]};
|
} || [{rules, Rules}] <- ets:select(?ACL_TABLE, MatchSpec)]};
|
||||||
tickets(post, #{bindings := #{type := <<"username">>},
|
records(post, #{bindings := #{type := <<"username">>},
|
||||||
body := #{<<"username">> := Username, <<"rules">> := Rules}}) ->
|
body := #{<<"username">> := Username, <<"rules">> := Rules}}) ->
|
||||||
Ticket = #emqx_acl{
|
Record = #emqx_acl{
|
||||||
who = {username, Username},
|
who = {username, Username},
|
||||||
rules = format_rules(Rules)
|
rules = format_rules(Rules)
|
||||||
},
|
},
|
||||||
case ret(mnesia:transaction(fun insert/1, [Ticket])) of
|
case ret(mnesia:transaction(fun insert/1, [Record])) of
|
||||||
ok -> {204};
|
ok -> {204};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{400, #{code => <<"BAD_REQUEST">>,
|
{400, #{code => <<"BAD_REQUEST">>,
|
||||||
message => atom_to_binary(Reason)}}
|
message => atom_to_binary(Reason)}}
|
||||||
end;
|
end;
|
||||||
tickets(post, #{bindings := #{type := <<"clientid">>},
|
records(post, #{bindings := #{type := <<"clientid">>},
|
||||||
body := #{<<"clientid">> := Clientid, <<"rules">> := Rules}}) ->
|
body := #{<<"clientid">> := Clientid, <<"rules">> := Rules}}) ->
|
||||||
Ticket = #emqx_acl{
|
Record = #emqx_acl{
|
||||||
who = {clientid, Clientid},
|
who = {clientid, Clientid},
|
||||||
rules = format_rules(Rules)
|
rules = format_rules(Rules)
|
||||||
},
|
},
|
||||||
case ret(mnesia:transaction(fun insert/1, [Ticket])) of
|
case ret(mnesia:transaction(fun insert/1, [Record])) of
|
||||||
ok -> {204};
|
ok -> {204};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{400, #{code => <<"BAD_REQUEST">>,
|
{400, #{code => <<"BAD_REQUEST">>,
|
||||||
message => atom_to_binary(Reason)}}
|
message => atom_to_binary(Reason)}}
|
||||||
end;
|
end;
|
||||||
tickets(put, #{bindings := #{type := <<"all">>},
|
records(put, #{bindings := #{type := <<"all">>},
|
||||||
body := #{<<"rules">> := Rules}}) ->
|
body := #{<<"rules">> := Rules}}) ->
|
||||||
Ticket = #emqx_acl{
|
Record = #emqx_acl{
|
||||||
who = all,
|
who = all,
|
||||||
rules = format_rules(Rules)
|
rules = format_rules(Rules)
|
||||||
},
|
},
|
||||||
case ret(mnesia:transaction(fun mnesia:write/1, [Ticket])) of
|
case ret(mnesia:transaction(fun ekka_mnesia:dirty_write/1, [Record])) of
|
||||||
ok -> {204};
|
ok -> {204};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{400, #{code => <<"BAD_REQUEST">>,
|
{400, #{code => <<"BAD_REQUEST">>,
|
||||||
message => atom_to_binary(Reason)}}
|
message => atom_to_binary(Reason)}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
ticket(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
|
||||||
[] -> {404, #{code => <<"NOT_FOUND">>, message => <<"Not Found">>}};
|
[] -> {404, #{code => <<"NOT_FOUND">>, message => <<"Not Found">>}};
|
||||||
[#emqx_acl{who = {username, Username}, rules = Rules}] ->
|
[#emqx_acl{who = {username, Username}, rules = Rules}] ->
|
||||||
|
@ -468,7 +468,7 @@ ticket(get, #{bindings := #{type := <<"username">>, key := Key}}) ->
|
||||||
} || {Permission, Action, Topic} <- Rules]}
|
} || {Permission, Action, Topic} <- Rules]}
|
||||||
}
|
}
|
||||||
end;
|
end;
|
||||||
ticket(get, #{bindings := #{type := <<"clientid">>, key := Key}}) ->
|
record(get, #{bindings := #{type := <<"clientid">>, key := Key}}) ->
|
||||||
case mnesia:dirty_read(?ACL_TABLE, {clientid, Key}) of
|
case mnesia:dirty_read(?ACL_TABLE, {clientid, Key}) of
|
||||||
[] -> {404, #{code => <<"NOT_FOUND">>, message => <<"Not Found">>}};
|
[] -> {404, #{code => <<"NOT_FOUND">>, message => <<"Not Found">>}};
|
||||||
[#emqx_acl{who = {clientid, Clientid}, rules = Rules}] ->
|
[#emqx_acl{who = {clientid, Clientid}, rules = Rules}] ->
|
||||||
|
@ -479,7 +479,7 @@ ticket(get, #{bindings := #{type := <<"clientid">>, key := Key}}) ->
|
||||||
} || {Permission, Action, Topic} <- Rules]}
|
} || {Permission, Action, Topic} <- Rules]}
|
||||||
}
|
}
|
||||||
end;
|
end;
|
||||||
ticket(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
|
case ret(mnesia:transaction(fun update/2, [{username, Username}, format_rules(Rules)])) of
|
||||||
ok -> {204};
|
ok -> {204};
|
||||||
|
@ -487,7 +487,7 @@ ticket(put, #{bindings := #{type := <<"username">>, key := Username},
|
||||||
{400, #{code => <<"BAD_REQUEST">>,
|
{400, #{code => <<"BAD_REQUEST">>,
|
||||||
message => atom_to_binary(Reason)}}
|
message => atom_to_binary(Reason)}}
|
||||||
end;
|
end;
|
||||||
ticket(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
|
case ret(mnesia:transaction(fun update/2, [{clientid, Clientid}, format_rules(Rules)])) of
|
||||||
ok -> {204};
|
ok -> {204};
|
||||||
|
@ -495,15 +495,15 @@ ticket(put, #{bindings := #{type := <<"clientid">>, key := Clientid},
|
||||||
{400, #{code => <<"BAD_REQUEST">>,
|
{400, #{code => <<"BAD_REQUEST">>,
|
||||||
message => atom_to_binary(Reason)}}
|
message => atom_to_binary(Reason)}}
|
||||||
end;
|
end;
|
||||||
ticket(delete, #{bindings := #{type := <<"username">>, key := Key}}) ->
|
record(delete, #{bindings := #{type := <<"username">>, key := Key}}) ->
|
||||||
case ret(mnesia:transaction(fun mnesia:delete/1, [{?ACL_TABLE, {username, Key}}])) of
|
case ret(mnesia:transaction(fun ekka_mnesia:dirty_delete/1, [{?ACL_TABLE, {username, Key}}])) of
|
||||||
ok -> {204};
|
ok -> {204};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{400, #{code => <<"BAD_REQUEST">>,
|
{400, #{code => <<"BAD_REQUEST">>,
|
||||||
message => atom_to_binary(Reason)}}
|
message => atom_to_binary(Reason)}}
|
||||||
end;
|
end;
|
||||||
ticket(delete, #{bindings := #{type := <<"clientid">>, key := Key}}) ->
|
record(delete, #{bindings := #{type := <<"clientid">>, key := Key}}) ->
|
||||||
case ret(mnesia:transaction(fun mnesia:delete/1, [{?ACL_TABLE, {clientid, Key}}])) of
|
case ret(mnesia:transaction(fun ekka_mnesia:dirty_delete/1, [{?ACL_TABLE, {clientid, Key}}])) of
|
||||||
ok -> {204};
|
ok -> {204};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{400, #{code => <<"BAD_REQUEST">>,
|
{400, #{code => <<"BAD_REQUEST">>,
|
||||||
|
@ -526,16 +526,16 @@ atom(B) when is_binary(B) ->
|
||||||
end;
|
end;
|
||||||
atom(A) when is_atom(A) -> A.
|
atom(A) when is_atom(A) -> A.
|
||||||
|
|
||||||
insert(Ticket = #emqx_acl{who = Who}) ->
|
insert(Record = #emqx_acl{who = Who}) ->
|
||||||
case mnesia:read(?ACL_TABLE, Who) of
|
case mnesia:read(?ACL_TABLE, Who) of
|
||||||
[] -> mnesia:write(Ticket);
|
[] -> ekka_mnesia:dirty_write(Record);
|
||||||
[_|_] -> mnesia:abort(existed)
|
[_|_] -> mnesia:abort(existed)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
update(Who, Rules) ->
|
update(Who, Rules) ->
|
||||||
case mnesia:read(?ACL_TABLE, Who) of
|
case mnesia:read(?ACL_TABLE, Who) of
|
||||||
[#emqx_acl{} = Ticket] ->
|
[#emqx_acl{} = Record] ->
|
||||||
mnesia:write(Ticket#emqx_acl{rules = Rules});
|
ekka_mnesia:dirty_write(Record#emqx_acl{rules = Rules});
|
||||||
[] -> mnesia:abort(noexisted)
|
[] -> mnesia:abort(noexisted)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
|
@ -54,24 +54,24 @@ end_per_suite(_Config) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
init_per_testcase(t_authz, Config) ->
|
init_per_testcase(t_authz, Config) ->
|
||||||
mnesia:transaction(fun mnesia:write/1, [#emqx_acl{who = {username, <<"test_username">>},
|
mnesia:transaction(fun ekka_mnesia:dirty_write/1, [#emqx_acl{who = {username, <<"test_username">>},
|
||||||
rules = [{allow, publish, <<"test/%u">>},
|
rules = [{allow, publish, <<"test/%u">>},
|
||||||
{allow, subscribe, <<"eq #">>}
|
{allow, subscribe, <<"eq #">>}
|
||||||
]
|
]
|
||||||
}]),
|
}]),
|
||||||
mnesia:transaction(fun mnesia:write/1, [#emqx_acl{who = {clientid, <<"test_clientid">>},
|
mnesia:transaction(fun ekka_mnesia:dirty_write/1, [#emqx_acl{who = {clientid, <<"test_clientid">>},
|
||||||
rules = [{allow, publish, <<"test/%c">>},
|
rules = [{allow, publish, <<"test/%c">>},
|
||||||
{deny, subscribe, <<"eq #">>}
|
{deny, subscribe, <<"eq #">>}
|
||||||
]
|
]
|
||||||
}]),
|
}]),
|
||||||
mnesia:transaction(fun mnesia:write/1, [#emqx_acl{who = all,
|
mnesia:transaction(fun ekka_mnesia:dirty_write/1, [#emqx_acl{who = all,
|
||||||
rules = [{deny, all, <<"#">>}]
|
rules = [{deny, all, <<"#">>}]
|
||||||
}]),
|
}]),
|
||||||
Config;
|
Config;
|
||||||
init_per_testcase(_, Config) -> Config.
|
init_per_testcase(_, Config) -> Config.
|
||||||
|
|
||||||
end_per_testcase(t_authz, Config) ->
|
end_per_testcase(t_authz, Config) ->
|
||||||
[ mnesia:dirty_delete(?ACL_TABLE, K) || K <- mnesia:dirty_all_keys(?ACL_TABLE)],
|
[ ekka_mnesia:dirty_delete(?ACL_TABLE, K) || K <- mnesia:dirty_all_keys(?ACL_TABLE)],
|
||||||
Config;
|
Config;
|
||||||
end_per_testcase(_, Config) -> Config.
|
end_per_testcase(_, Config) -> Config.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue