Authz api mnesia refactor (#6082)

* refactor(authz): macro move to hrl and rename, add meta example

* refactor(authz_api_mnesia): use config schemas for request validations

* chore(authz_api_mnesia): suite module typerefl fit

* chore(style): authz_api_mnesia style format
This commit is contained in:
JimMoen 2021-11-11 16:29:36 +08:00 committed by GitHub
parent 3c1ae385ee
commit a65597e302
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 379 additions and 492 deletions

View File

@ -67,3 +67,52 @@
-define(AUTHZ_METRICS(K), ?METRICS(authz_metrics, K)).
-define(CONF_KEY_PATH, [authorization, sources]).
-define(USERNAME_RULES_EXAMPLE, #{username => user1,
rules => [ #{topic => <<"test/toopic/1">>,
permission => <<"allow">>,
action => <<"publish">>
}
, #{topic => <<"test/toopic/2">>,
permission => <<"allow">>,
action => <<"subscribe">>
}
, #{topic => <<"eq test/#">>,
permission => <<"deny">>,
action => <<"all">>
}
]
}).
-define(CLIENTID_RULES_EXAMPLE, #{clientid => client1,
rules => [ #{topic => <<"test/toopic/1">>,
permission => <<"allow">>,
action => <<"publish">>
}
, #{topic => <<"test/toopic/2">>,
permission => <<"allow">>,
action => <<"subscribe">>
}
, #{topic => <<"eq test/#">>,
permission => <<"deny">>,
action => <<"all">>
}
]
}).
-define(ALL_RULES_EXAMPLE, #{rules => [ #{topic => <<"test/toopic/1">>,
permission => <<"allow">>,
action => <<"publish">>
}
, #{topic => <<"test/toopic/2">>,
permission => <<"allow">>,
action => <<"subscribe">>
}
, #{topic => <<"eq test/#">>,
permission => <<"deny">>,
action => <<"all">>
}
]
}).
-define(META_EXAMPLE, #{ page => 1
, limit => 100
, count => 1
}).

View File

@ -21,492 +21,252 @@
-include("emqx_authz.hrl").
-include_lib("emqx/include/logger.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
-include_lib("typerefl/include/types.hrl").
-define(EXAMPLE_USERNAME, #{username => user1,
rules => [ #{topic => <<"test/toopic/1">>,
permission => <<"allow">>,
action => <<"publish">>
}
, #{topic => <<"test/toopic/2">>,
permission => <<"allow">>,
action => <<"subscribe">>
}
, #{topic => <<"eq test/#">>,
permission => <<"deny">>,
action => <<"all">>
}
]
}).
-define(EXAMPLE_CLIENTID, #{clientid => client1,
rules => [ #{topic => <<"test/toopic/1">>,
permission => <<"allow">>,
action => <<"publish">>
}
, #{topic => <<"test/toopic/2">>,
permission => <<"allow">>,
action => <<"subscribe">>
}
, #{topic => <<"eq test/#">>,
permission => <<"deny">>,
action => <<"all">>
}
]
}).
-define(EXAMPLE_ALL , #{rules => [ #{topic => <<"test/toopic/1">>,
permission => <<"allow">>,
action => <<"publish">>
}
, #{topic => <<"test/toopic/2">>,
permission => <<"allow">>,
action => <<"subscribe">>
}
, #{topic => <<"eq test/#">>,
permission => <<"deny">>,
action => <<"all">>
}
]
}).
-define(FORMAT_USERNAME_FUN, {?MODULE, format_by_username}).
-define(FORMAT_CLIENTID_FUN, {?MODULE, format_by_clientid}).
-export([ api_spec/0
, purge/2
, users/2
, user/2
, paths/0
, schema/1
, fields/1
]).
%% operation funs
-export([ users/2
, clients/2
, user/2
, client/2
, all/2
, purge/2
]).
-export([ format_by_username/1
, format_by_clientid/1]).
-define(BAD_REQUEST, 'BAD_REQUEST').
-define(NOT_FOUND, 'NOT_FOUND').
-define(TYPE_REF, ref).
-define(TYPE_ARRAY, array).
-define(PAGE_QUERY_EXAMPLE, example_in_data).
-define(PUT_MAP_EXAMPLE, in_put_requestBody).
-define(POST_ARRAY_EXAMPLE, in_post_requestBody).
api_spec() ->
{[ purge_api()
, users_api()
, user_api()
, clients_api()
, client_api()
, all_api()
], definitions()}.
emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
definitions() ->
Rules = #{
type => array,
items => #{
type => object,
required => [topic, permission, action],
properties => #{
topic => #{
type => string,
example => <<"test/topic/1">>
},
permission => #{
type => string,
enum => [<<"allow">>, <<"deny">>],
example => <<"allow">>
},
action => #{
type => string,
enum => [<<"publish">>, <<"subscribe">>, <<"all">>],
example => <<"publish">>
}
}
}
},
Username = #{
type => object,
required => [username, rules],
properties => #{
username => #{
type => string,
example => <<"username">>
},
rules => minirest:ref(<<"rules">>)
}
},
Clientid = #{
type => object,
required => [clientid, rules],
properties => #{
clientid => #{
type => string,
example => <<"clientid">>
},
rules => minirest:ref(<<"rules">>)
}
},
ALL = #{
type => object,
required => [rules],
properties => #{
rules => minirest:ref(<<"rules">>)
}
},
[ #{<<"rules">> => Rules}
, #{<<"username">> => Username}
, #{<<"clientid">> => Clientid}
, #{<<"all">> => ALL}
].
paths() ->
[ "/authorization/sources/built-in-database/username"
, "/authorization/sources/built-in-database/clientid"
, "/authorization/sources/built-in-database/username/:username"
, "/authorization/sources/built-in-database/clientid/:clientid"
, "/authorization/sources/built-in-database/all"
, "/authorization/sources/built-in-database/purge-all"].
users_api() ->
Metadata = #{
%%--------------------------------------------------------------------
%% Schema for each URI
%%--------------------------------------------------------------------
schema("/authorization/sources/built-in-database/username") ->
#{
'operationId' => users,
get => #{
description => "Show the list of record for username",
parameters => [
#{
name => page,
in => query,
required => false,
description => <<"Page Index">>,
schema => #{type => integer}
},
#{
name => limit,
in => query,
required => false,
description => <<"Page limit">>,
schema => #{type => integer}
}
],
tags => [<<"authorization">>],
description => <<"Show the list of record for username">>,
parameters => [ hoconsc:ref(emqx_dashboard_swagger, page)
, hoconsc:ref(emqx_dashboard_swagger, limit)],
responses => #{
<<"200">> => #{
description => <<"OK">>,
content => #{
'application/json' => #{
schema => #{
type => array,
items => minirest:ref(<<"username">>)
},
examples => #{
username => #{
summary => <<"Username">>,
value => jsx:encode([?EXAMPLE_USERNAME])
}
}
}
}
}
200 => swagger_with_example( {username_response_data, ?TYPE_REF}
, {username, ?PAGE_QUERY_EXAMPLE})
}
},
post => #{
description => "Add new records for username",
requestBody => #{
content => #{
'application/json' => #{
schema => #{
type => array,
items => #{
oneOf => [ minirest:ref(<<"username">>)
]
}
},
examples => #{
username => #{
summary => <<"Username">>,
value => jsx:encode([?EXAMPLE_USERNAME])
}
}
}
}
},
tags => [<<"authorization">>],
description => <<"Add new records for username">>,
'requestBody' => swagger_with_example( {rules_for_username, ?TYPE_ARRAY}
, {username, ?POST_ARRAY_EXAMPLE}),
responses => #{
<<"204">> => #{description => <<"Created">>},
<<"400">> => emqx_mgmt_util:bad_request()
204 => <<"Created">>,
400 => emqx_dashboard_swagger:error_codes( [?BAD_REQUEST]
, <<"Bad username or bad rule schema">>)
}
}
},
{"/authorization/sources/built-in-database/username", Metadata, users}.
clients_api() ->
Metadata = #{
};
schema("/authorization/sources/built-in-database/clientid") ->
#{
'operationId' => clients,
get => #{
description => "Show the list of record for clientid",
parameters => [
#{
name => page,
in => query,
required => false,
description => <<"Page Index">>,
schema => #{type => integer}
},
#{
name => limit,
in => query,
required => false,
description => <<"Page limit">>,
schema => #{type => integer}
}
],
tags => [<<"authorization">>],
description => <<"Show the list of record for clientid">>,
parameters => [ hoconsc:ref(emqx_dashboard_swagger, page)
, hoconsc:ref(emqx_dashboard_swagger, limit)],
responses => #{
<<"200">> => #{
description => <<"OK">>,
content => #{
'application/json' => #{
schema => #{
type => array,
items => minirest:ref(<<"clientid">>)
},
examples => #{
clientid => #{
summary => <<"Clientid">>,
value => jsx:encode([?EXAMPLE_CLIENTID])
}
}
}
}
}
200 => swagger_with_example( {clientid_response_data, ?TYPE_REF}
, {clientid, ?PAGE_QUERY_EXAMPLE})
}
},
post => #{
description => "Add new records for clientid",
requestBody => #{
content => #{
'application/json' => #{
schema => #{
type => array,
items => #{
oneOf => [ minirest:ref(<<"clientid">>)
]
}
},
examples => #{
clientid => #{
summary => <<"Clientid">>,
value => jsx:encode([?EXAMPLE_CLIENTID])
}
}
}
}
},
tags => [<<"authorization">>],
description => <<"Add new records for clientid">>,
'requestBody' => swagger_with_example( {rules_for_clientid, ?TYPE_ARRAY}
, {clientid, ?POST_ARRAY_EXAMPLE}),
responses => #{
<<"204">> => #{description => <<"Created">>},
<<"400">> => emqx_mgmt_util:bad_request()
204 => <<"Created">>,
400 => emqx_dashboard_swagger:error_codes( [?BAD_REQUEST]
, <<"Bad clientid or bad rule schema">>)
}
}
},
{"/authorization/sources/built-in-database/clientid", Metadata, clients}.
user_api() ->
Metadata = #{
};
schema("/authorization/sources/built-in-database/username/:username") ->
#{
'operationId' => user,
get => #{
description => "Get record info for username",
parameters => [
#{
name => username,
in => path,
schema => #{
type => string
},
required => true
}
],
tags => [<<"authorization">>],
description => <<"Get record info for username">>,
parameters => [hoconsc:ref(username)],
responses => #{
<<"200">> => #{
description => <<"OK">>,
content => #{
'application/json' => #{
schema => minirest:ref(<<"username">>),
examples => #{
username => #{
summary => <<"Username">>,
value => jsx:encode(?EXAMPLE_USERNAME)
}
}
}
}
},
<<"404">> => emqx_mgmt_util:bad_request(<<"Not Found">>)
200 => swagger_with_example( {rules_for_username, ?TYPE_REF}
, {username, ?PUT_MAP_EXAMPLE}),
404 => emqx_dashboard_swagger:error_codes([?NOT_FOUND], <<"Not Found">>)
}
},
put => #{
description => "Set record for username",
parameters => [
#{
name => username,
in => path,
schema => #{
type => string
},
required => true
}
],
requestBody => #{
content => #{
'application/json' => #{
schema => minirest:ref(<<"username">>),
examples => #{
username => #{
summary => <<"Username">>,
value => jsx:encode(?EXAMPLE_USERNAME)
}
}
}
}
},
tags => [<<"authorization">>],
description => <<"Set record for username">>,
parameters => [hoconsc:ref(username)],
'requestBody' => swagger_with_example( {rules_for_username, ?TYPE_REF}
, {username, ?PUT_MAP_EXAMPLE}),
responses => #{
<<"204">> => #{description => <<"Updated">>},
<<"400">> => emqx_mgmt_util:bad_request()
204 => <<"Updated">>,
400 => emqx_dashboard_swagger:error_codes( [?BAD_REQUEST]
, <<"Bad username or bad rule schema">>)
}
},
delete => #{
description => "Delete one record for username",
parameters => [
#{
name => username,
in => path,
schema => #{
type => string
},
required => true
}
],
tags => [<<"authorization">>],
description => <<"Delete one record for username">>,
parameters => [hoconsc:ref(username)],
responses => #{
<<"204">> => #{description => <<"No Content">>},
<<"400">> => emqx_mgmt_util:bad_request()
204 => <<"No Content">>,
400 => emqx_dashboard_swagger:error_codes([?BAD_REQUEST], <<"Bad username">>)
}
}
},
{"/authorization/sources/built-in-database/username/:username", Metadata, user}.
client_api() ->
Metadata = #{
};
schema("/authorization/sources/built-in-database/clientid/:clientid") ->
#{
'operationId' => client,
get => #{
description => "Get record info for clientid",
parameters => [
#{
name => clientid,
in => path,
schema => #{
type => string
},
required => true
}
],
tags => [<<"authorization">>],
description => <<"Get record info for clientid">>,
parameters => [hoconsc:ref(clientid)],
responses => #{
<<"200">> => #{
description => <<"OK">>,
content => #{
'application/json' => #{
schema => minirest:ref(<<"clientid">>),
examples => #{
clientid => #{
summary => <<"Clientid">>,
value => jsx:encode(?EXAMPLE_CLIENTID)
}
}
}
}
},
<<"404">> => emqx_mgmt_util:bad_request(<<"Not Found">>)
200 => swagger_with_example( {rules_for_clientid, ?TYPE_REF}
, {clientid, ?PUT_MAP_EXAMPLE}),
404 => emqx_dashboard_swagger:error_codes([?NOT_FOUND], <<"Not Found">>)
}
},
put => #{
description => "Set record for clientid",
parameters => [
#{
name => clientid,
in => path,
schema => #{
type => string
},
required => true
}
],
requestBody => #{
content => #{
'application/json' => #{
schema => minirest:ref(<<"clientid">>),
examples => #{
clientid => #{
summary => <<"Clientid">>,
value => jsx:encode(?EXAMPLE_CLIENTID)
}
}
}
}
},
tags => [<<"authorization">>],
description => <<"Set record for clientid">>,
parameters => [hoconsc:ref(clientid)],
'requestBody' => swagger_with_example( {rules_for_clientid, ?TYPE_REF}
, {clientid, ?PUT_MAP_EXAMPLE}),
responses => #{
<<"204">> => #{description => <<"Updated">>},
<<"400">> => emqx_mgmt_util:bad_request()
204 => <<"Updated">>,
400 => emqx_dashboard_swagger:error_codes(
[?BAD_REQUEST], <<"Bad clientid or bad rule schema">>)
}
},
delete => #{
description => "Delete one record for clientid",
parameters => [
#{
name => clientid,
in => path,
schema => #{
type => string
},
required => true
}
],
tags => [<<"authorization">>],
description => <<"Delete one record for clientid">>,
parameters => [hoconsc:ref(clientid)],
responses => #{
<<"204">> => #{description => <<"No Content">>},
<<"400">> => emqx_mgmt_util:bad_request()
204 => <<"No Content">>,
400 => emqx_dashboard_swagger:error_codes([?BAD_REQUEST], <<"Bad clientid">>)
}
}
},
{"/authorization/sources/built-in-database/clientid/:clientid", Metadata, client}.
all_api() ->
Metadata = #{
};
schema("/authorization/sources/built-in-database/all") ->
#{
'operationId' => all,
get => #{
description => "Show the list of rules for all",
tags => [<<"authorization">>],
description => <<"Show the list of rules for all">>,
responses => #{
<<"200">> => #{
description => <<"OK">>,
content => #{
'application/json' => #{
schema => minirest:ref(<<"clientid">>),
examples => #{
clientid => #{
summary => <<"All">>,
value => jsx:encode(?EXAMPLE_ALL)
}
}
}
}
}
200 => swagger_with_example({rules_for_all, ?TYPE_REF}, {all, ?PUT_MAP_EXAMPLE})
}
},
put => #{
description => "Set the list of rules for all",
requestBody => #{
content => #{
'application/json' => #{
schema => minirest:ref(<<"all">>),
examples => #{
all => #{
summary => <<"All">>,
value => jsx:encode(?EXAMPLE_ALL)
}
}
}
}
},
tags => [<<"authorization">>],
description => <<"Set the list of rules for all">>,
'requestBody' =>
swagger_with_example({rules_for_all, ?TYPE_REF}, {all, ?PUT_MAP_EXAMPLE}),
responses => #{
<<"204">> => #{description => <<"Created">>},
<<"400">> => emqx_mgmt_util:bad_request()
204 => <<"Created">>,
400 => emqx_dashboard_swagger:error_codes([?BAD_REQUEST], <<"Bad rule schema">>)
}
}
},
{"/authorization/sources/built-in-database/all", Metadata, all}.
purge_api() ->
Metadata = #{
};
schema("/authorization/sources/built-in-database/purge-all") ->
#{
'operationId' => purge,
delete => #{
description => "Purge all records",
tags => [<<"authorization">>],
description => <<"Purge all records">>,
responses => #{
<<"204">> => #{description => <<"No Content">>},
<<"400">> => emqx_mgmt_util:bad_request()
204 => <<"No Content">>,
400 => emqx_dashboard_swagger:error_codes([?BAD_REQUEST], <<"Bad Request">>)
}
}
},
{"/authorization/sources/built-in-database/purge-all", Metadata, purge}.
}.
fields(rule_item) ->
[ {topic, hoconsc:mk( string()
, #{ required => true
, desc => <<"Rule on specific topic">>
, example => <<"test/topic/1">>})}
, {permission, hoconsc:mk( hoconsc:enum([allow, deny])
, #{desc => <<"Permission">>, required => true, example => allow})}
, {action, hoconsc:mk( hoconsc:enum([publish, subscribe, all])
, #{ required => true, example => publish
, desc => <<"Authorized action">> })} ];
fields(clientid) ->
[ {clientid, hoconsc:mk( binary()
, #{ in => path, required => true
, desc => <<"ClientID">>, example => <<"client1">>})}
];
fields(username) ->
[ {username, hoconsc:mk( binary()
, #{ in => path, required => true
, desc => <<"Username">>, example => <<"user1">>})}
];
fields(rules_for_username) ->
[ {rules, hoconsc:mk(hoconsc:array(hoconsc:ref(rule_item)), #{})}
] ++ fields(username);
fields(username_response_data) ->
[ {data, hoconsc:mk(hoconsc:array(hoconsc:ref(rules_for_username)), #{})}
, {meta, hoconsc:ref(meta)}
];
fields(rules_for_clientid) ->
[ {rules, hoconsc:mk(hoconsc:array(hoconsc:ref(rule_item)), #{})}
] ++ fields(clientid);
fields(clientid_response_data) ->
[ {data, hoconsc:mk(hoconsc:array(hoconsc:ref(rules_for_clientid)), #{})}
, {meta, hoconsc:ref(meta)}
];
fields(rules_for_all) ->
[ {rules, hoconsc:mk(hoconsc:array(hoconsc:ref(rule_item)), #{})}
];
fields(meta) ->
emqx_dashboard_swagger:fields(page)
++ emqx_dashboard_swagger:fields(limit)
++ [{count, hoconsc:mk(integer(), #{example => 1})}].
%%--------------------------------------------------------------------
%% HTTP API
%%--------------------------------------------------------------------
users(get, #{query_string := PageParams}) ->
MatchSpec = ets:fun2ms(
@ -609,7 +369,8 @@ purge(delete, _) ->
{204};
[#{<<"enable">> := true}] ->
{400, #{code => <<"BAD_REQUEST">>,
message => <<"'built-in-database' type source must be disabled before purge.">>}};
message =>
<<"'built-in-database' type source must be disabled before purge.">>}};
[] ->
{404, #{code => <<"BAD_REQUEST">>,
message => <<"'built-in-database' type source is not found.">>
@ -642,6 +403,43 @@ format_by_clientid([{clientid, Clientid}, {rules, Rules}]) ->
atom(B) when is_binary(B) ->
try binary_to_existing_atom(B, utf8)
catch
_ -> binary_to_atom(B)
_Error:_Expection -> binary_to_atom(B)
end;
atom(A) when is_atom(A) -> A.
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
swagger_with_example({Ref, TypeP}, {_Name, _Type} = Example) ->
emqx_dashboard_swagger:schema_with_examples(
case TypeP of
?TYPE_REF -> hoconsc:ref(?MODULE, Ref);
?TYPE_ARRAY -> hoconsc:array(hoconsc:ref(?MODULE, Ref))
end,
rules_example(Example)).
rules_example({ExampleName, ExampleType}) ->
{Summary, Example} =
case ExampleName of
username -> {<<"Username">>, ?USERNAME_RULES_EXAMPLE};
clientid -> {<<"ClientID">>, ?CLIENTID_RULES_EXAMPLE};
all -> {<<"All">>, ?ALL_RULES_EXAMPLE}
end,
Value =
case ExampleType of
?PAGE_QUERY_EXAMPLE -> #{
data => [Example],
meta => ?META_EXAMPLE
};
?PUT_MAP_EXAMPLE ->
Example;
?POST_ARRAY_EXAMPLE ->
[Example]
end,
#{
'password-based:built-in-database' => #{
summary => Summary,
value => Value
}
}.

View File

@ -35,50 +35,6 @@ authorization
-define(API_VERSION, "v5").
-define(BASE_PATH, "api").
-define(EXAMPLE_USERNAME, #{username => user1,
rules => [ #{topic => <<"test/toopic/1">>,
permission => <<"allow">>,
action => <<"publish">>
}
, #{topic => <<"test/toopic/2">>,
permission => <<"allow">>,
action => <<"subscribe">>
}
, #{topic => <<"eq test/#">>,
permission => <<"deny">>,
action => <<"all">>
}
]
}).
-define(EXAMPLE_CLIENTID, #{clientid => client1,
rules => [ #{topic => <<"test/toopic/1">>,
permission => <<"allow">>,
action => <<"publish">>
}
, #{topic => <<"test/toopic/2">>,
permission => <<"allow">>,
action => <<"subscribe">>
}
, #{topic => <<"eq test/#">>,
permission => <<"deny">>,
action => <<"all">>
}
]
}).
-define(EXAMPLE_ALL , #{rules => [ #{topic => <<"test/toopic/1">>,
permission => <<"allow">>,
action => <<"publish">>
}
, #{topic => <<"test/toopic/2">>,
permission => <<"allow">>,
action => <<"subscribe">>
}
, #{topic => <<"eq test/#">>,
permission => <<"deny">>,
action => <<"all">>
}
]
}).
roots() -> ["authorization"].
@ -126,65 +82,149 @@ set_special_configs(_App) ->
%%------------------------------------------------------------------------------
t_api(_) ->
{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, Request2} = request(get, uri(["authorization", "sources", "built-in-database", "username", "user1"]), []),
{ok, 204, _} =
request( post
, uri(["authorization", "sources", "built-in-database", "username"])
, [?USERNAME_RULES_EXAMPLE]),
{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"])
, []),
#{<<"data">> := [#{<<"username">> := <<"user1">>, <<"rules">> := Rules1}],
<<"meta">> := #{<<"count">> := 1,<<"limit">> := 100,<<"page">> := 1}} = jsx:decode(Request1),
#{<<"username">> := <<"user1">>, <<"rules">> := Rules1} = jsx:decode(Request2),
?assertEqual(3, length(Rules1)),
{ok, 204, _} = request(put, uri(["authorization", "sources", "built-in-database", "username", "user1"]), ?EXAMPLE_USERNAME#{rules => []}),
{ok, 200, Request3} = request(get, uri(["authorization", "sources", "built-in-database", "username", "user1"]), []),
{ok, 204, _} =
request( put
, uri(["authorization", "sources", "built-in-database", "username", "user1"])
, ?USERNAME_RULES_EXAMPLE#{rules => []}),
{ok, 200, Request3} =
request( get
, uri(["authorization", "sources", "built-in-database", "username", "user1"])
, []),
#{<<"username">> := <<"user1">>, <<"rules">> := Rules2} = jsx:decode(Request3),
?assertEqual(0, length(Rules2)),
{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, 204, _} =
request( delete
, 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, 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, 204, _} =
request( post
, uri(["authorization", "sources", "built-in-database", "clientid"])
, [?CLIENTID_RULES_EXAMPLE]),
{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"])
, []),
#{<<"data">> := [#{<<"clientid">> := <<"client1">>, <<"rules">> := Rules3}],
<<"meta">> := #{<<"count">> := 1, <<"limit">> := 100, <<"page">> := 1}} = jsx:decode(Request4),
<<"meta">> := #{<<"count">> := 1, <<"limit">> := 100, <<"page">> := 1}}
= jsx:decode(Request4),
#{<<"clientid">> := <<"client1">>, <<"rules">> := Rules3} = jsx:decode(Request5),
?assertEqual(3, length(Rules3)),
{ok, 204, _} = request(put, uri(["authorization", "sources", "built-in-database", "clientid", "client1"]), ?EXAMPLE_CLIENTID#{rules => []}),
{ok, 200, Request6} = request(get, uri(["authorization", "sources", "built-in-database", "clientid", "client1"]), []),
{ok, 204, _} =
request( put
, uri(["authorization", "sources", "built-in-database", "clientid", "client1"])
, ?CLIENTID_RULES_EXAMPLE#{rules => []}),
{ok, 200, Request6} =
request( get
, uri(["authorization", "sources", "built-in-database", "clientid", "client1"])
, []),
#{<<"clientid">> := <<"client1">>, <<"rules">> := Rules4} = jsx:decode(Request6),
?assertEqual(0, length(Rules4)),
{ok, 204, _} = request(delete, uri(["authorization", "sources", "built-in-database", "clientid", "client1"]), []),
{ok, 404, _} = request(get, uri(["authorization", "sources", "built-in-database", "clientid", "client1"]), []),
{ok, 204, _} =
request( delete
, uri(["authorization", "sources", "built-in-database", "clientid", "client1"])
, []),
{ok, 404, _} =
request( get
, uri(["authorization", "sources", "built-in-database", "clientid", "client1"])
, []),
{ok, 204, _} = request(put, uri(["authorization", "sources", "built-in-database", "all"]), ?EXAMPLE_ALL),
{ok, 200, Request7} = request(get, uri(["authorization", "sources", "built-in-database", "all"]), []),
{ok, 204, _} =
request( put
, uri(["authorization", "sources", "built-in-database", "all"])
, ?ALL_RULES_EXAMPLE),
{ok, 200, Request7} =
request( get
, uri(["authorization", "sources", "built-in-database", "all"])
, []),
#{<<"rules">> := Rules5} = jsx:decode(Request7),
?assertEqual(3, length(Rules5)),
{ok, 204, _} = request(put, uri(["authorization", "sources", "built-in-database", "all"]), ?EXAMPLE_ALL#{rules => []}),
{ok, 200, Request8} = request(get, uri(["authorization", "sources", "built-in-database", "all"]), []),
{ok, 204, _} =
request( put
, uri(["authorization", "sources", "built-in-database", "all"])
, ?ALL_RULES_EXAMPLE#{rules => []}),
{ok, 200, Request8} =
request( get
, uri(["authorization", "sources", "built-in-database", "all"])
, []),
#{<<"rules">> := Rules6} = jsx:decode(Request8),
?assertEqual(0, length(Rules6)),
{ok, 204, _} = request(post, uri(["authorization", "sources", "built-in-database", "username"]), [ #{username => N, rules => []} || N <- lists:seq(1, 20) ]),
{ok, 200, Request9} = request(get, uri(["authorization", "sources", "built-in-database", "username?page=2&limit=5"]), []),
{ok, 204, _} =
request( post
, uri(["authorization", "sources", "built-in-database", "username"])
, [ #{username => erlang:integer_to_binary(N), rules => []}
|| N <- lists:seq(1, 20) ]),
{ok, 200, Request9} =
request( get
, uri(["authorization", "sources", "built-in-database", "username?page=2&limit=5"])
, []),
#{<<"data">> := Data1} = jsx:decode(Request9),
?assertEqual(5, length(Data1)),
{ok, 204, _} = request(post, uri(["authorization", "sources", "built-in-database", "clientid"]), [ #{clientid => N, rules => []} || N <- lists:seq(1, 20) ]),
{ok, 200, Request10} = request(get, uri(["authorization", "sources", "built-in-database", "clientid?limit=5"]), []),
{ok, 204, _} =
request( post
, uri(["authorization", "sources", "built-in-database", "clientid"])
, [ #{clientid => erlang:integer_to_binary(N), rules => []}
|| N <- lists:seq(1, 20) ]),
{ok, 200, Request10} =
request( get
, uri(["authorization", "sources", "built-in-database", "clientid?limit=5"])
, []),
#{<<"data">> := Data2} = jsx:decode(Request10),
?assertEqual(5, length(Data2)),
{ok, 400, Msg1} = request(delete, uri(["authorization", "sources", "built-in-database", "purge-all"]), []),
{ok, 400, Msg1} =
request( delete
, uri(["authorization", "sources", "built-in-database", "purge-all"])
, []),
?assertMatch({match, _}, re:run(Msg1, "must\sbe\sdisabled\sbefore")),
{ok, 204, _} = request(put, uri(["authorization", "sources", "built-in-database"]), #{<<"enable">> => true}),
{ok, 204, _} =
request( put
, uri(["authorization", "sources", "built-in-database"])
, #{<<"enable">> => true}),
%% test idempotence
{ok, 204, _} = request(put, uri(["authorization", "sources", "built-in-database"]), #{<<"enable">> => true}),
{ok, 204, _} = request(put, uri(["authorization", "sources", "built-in-database"]), #{<<"enable">> => false}),
{ok, 204, _} = request(delete, uri(["authorization", "sources", "built-in-database", "purge-all"]), []),
{ok, 204, _} =
request( put
, uri(["authorization", "sources", "built-in-database"])
, #{<<"enable">> => true}),
{ok, 204, _} =
request( put
, uri(["authorization", "sources", "built-in-database"])
, #{<<"enable">> => false}),
{ok, 204, _} =
request( delete
, uri(["authorization", "sources", "built-in-database", "purge-all"])
, []),
?assertEqual([], mnesia:dirty_all_keys(?ACL_TABLE)),
ok.