From a65597e302e32bd086ac3ecc006b62e8a94cd279 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Thu, 11 Nov 2021 16:29:36 +0800 Subject: [PATCH] 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 --- apps/emqx_authz/include/emqx_authz.hrl | 49 ++ apps/emqx_authz/src/emqx_authz_api_mnesia.erl | 638 ++++++------------ .../test/emqx_authz_api_mnesia_SUITE.erl | 184 +++-- 3 files changed, 379 insertions(+), 492 deletions(-) diff --git a/apps/emqx_authz/include/emqx_authz.hrl b/apps/emqx_authz/include/emqx_authz.hrl index c22b93c48..371d56e30 100644 --- a/apps/emqx_authz/include/emqx_authz.hrl +++ b/apps/emqx_authz/include/emqx_authz.hrl @@ -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 + }). diff --git a/apps/emqx_authz/src/emqx_authz_api_mnesia.erl b/apps/emqx_authz/src/emqx_authz_api_mnesia.erl index 77d5f155f..cafc8a27d 100644 --- a/apps/emqx_authz/src/emqx_authz_api_mnesia.erl +++ b/apps/emqx_authz/src/emqx_authz_api_mnesia.erl @@ -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 + } + }. diff --git a/apps/emqx_authz/test/emqx_authz_api_mnesia_SUITE.erl b/apps/emqx_authz/test/emqx_authz_api_mnesia_SUITE.erl index d9b308514..d07619146 100644 --- a/apps/emqx_authz/test/emqx_authz_api_mnesia_SUITE.erl +++ b/apps/emqx_authz/test/emqx_authz_api_mnesia_SUITE.erl @@ -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.