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(AUTHZ_METRICS(K), ?METRICS(authz_metrics, K)).
-define(CONF_KEY_PATH, [authorization, sources]). -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("emqx_authz.hrl").
-include_lib("emqx/include/logger.hrl"). -include_lib("emqx/include/logger.hrl").
-include_lib("stdlib/include/ms_transform.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_USERNAME_FUN, {?MODULE, format_by_username}).
-define(FORMAT_CLIENTID_FUN, {?MODULE, format_by_clientid}). -define(FORMAT_CLIENTID_FUN, {?MODULE, format_by_clientid}).
-export([ api_spec/0 -export([ api_spec/0
, purge/2 , paths/0
, users/2 , schema/1
, user/2 , fields/1
]).
%% operation funs
-export([ users/2
, clients/2 , clients/2
, user/2
, client/2 , client/2
, all/2 , all/2
, purge/2
]). ]).
-export([ format_by_username/1 -export([ format_by_username/1
, format_by_clientid/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() -> api_spec() ->
{[ purge_api() emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
, users_api()
, user_api()
, clients_api()
, client_api()
, all_api()
], definitions()}.
definitions() -> paths() ->
Rules = #{ [ "/authorization/sources/built-in-database/username"
type => array, , "/authorization/sources/built-in-database/clientid"
items => #{ , "/authorization/sources/built-in-database/username/:username"
type => object, , "/authorization/sources/built-in-database/clientid/:clientid"
required => [topic, permission, action], , "/authorization/sources/built-in-database/all"
properties => #{ , "/authorization/sources/built-in-database/purge-all"].
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}
].
users_api() -> %%--------------------------------------------------------------------
Metadata = #{ %% Schema for each URI
%%--------------------------------------------------------------------
schema("/authorization/sources/built-in-database/username") ->
#{
'operationId' => users,
get => #{ get => #{
description => "Show the list of record for username", tags => [<<"authorization">>],
parameters => [ description => <<"Show the list of record for username">>,
#{ parameters => [ hoconsc:ref(emqx_dashboard_swagger, page)
name => page, , hoconsc:ref(emqx_dashboard_swagger, limit)],
in => query,
required => false,
description => <<"Page Index">>,
schema => #{type => integer}
},
#{
name => limit,
in => query,
required => false,
description => <<"Page limit">>,
schema => #{type => integer}
}
],
responses => #{ responses => #{
<<"200">> => #{ 200 => swagger_with_example( {username_response_data, ?TYPE_REF}
description => <<"OK">>, , {username, ?PAGE_QUERY_EXAMPLE})
content => #{
'application/json' => #{
schema => #{
type => array,
items => minirest:ref(<<"username">>)
},
examples => #{
username => #{
summary => <<"Username">>,
value => jsx:encode([?EXAMPLE_USERNAME])
}
}
}
}
}
} }
}, },
post => #{ post => #{
description => "Add new records for username", tags => [<<"authorization">>],
requestBody => #{ description => <<"Add new records for username">>,
content => #{ 'requestBody' => swagger_with_example( {rules_for_username, ?TYPE_ARRAY}
'application/json' => #{ , {username, ?POST_ARRAY_EXAMPLE}),
schema => #{
type => array,
items => #{
oneOf => [ minirest:ref(<<"username">>)
]
}
},
examples => #{
username => #{
summary => <<"Username">>,
value => jsx:encode([?EXAMPLE_USERNAME])
}
}
}
}
},
responses => #{ responses => #{
<<"204">> => #{description => <<"Created">>}, 204 => <<"Created">>,
<<"400">> => emqx_mgmt_util:bad_request() 400 => emqx_dashboard_swagger:error_codes( [?BAD_REQUEST]
, <<"Bad username or bad rule schema">>)
} }
} }
}, };
{"/authorization/sources/built-in-database/username", Metadata, users}. schema("/authorization/sources/built-in-database/clientid") ->
#{
clients_api() -> 'operationId' => clients,
Metadata = #{
get => #{ get => #{
description => "Show the list of record for clientid", tags => [<<"authorization">>],
parameters => [ description => <<"Show the list of record for clientid">>,
#{ parameters => [ hoconsc:ref(emqx_dashboard_swagger, page)
name => page, , hoconsc:ref(emqx_dashboard_swagger, limit)],
in => query,
required => false,
description => <<"Page Index">>,
schema => #{type => integer}
},
#{
name => limit,
in => query,
required => false,
description => <<"Page limit">>,
schema => #{type => integer}
}
],
responses => #{ responses => #{
<<"200">> => #{ 200 => swagger_with_example( {clientid_response_data, ?TYPE_REF}
description => <<"OK">>, , {clientid, ?PAGE_QUERY_EXAMPLE})
content => #{
'application/json' => #{
schema => #{
type => array,
items => minirest:ref(<<"clientid">>)
},
examples => #{
clientid => #{
summary => <<"Clientid">>,
value => jsx:encode([?EXAMPLE_CLIENTID])
}
}
}
}
}
} }
}, },
post => #{ post => #{
description => "Add new records for clientid", tags => [<<"authorization">>],
requestBody => #{ description => <<"Add new records for clientid">>,
content => #{ 'requestBody' => swagger_with_example( {rules_for_clientid, ?TYPE_ARRAY}
'application/json' => #{ , {clientid, ?POST_ARRAY_EXAMPLE}),
schema => #{
type => array,
items => #{
oneOf => [ minirest:ref(<<"clientid">>)
]
}
},
examples => #{
clientid => #{
summary => <<"Clientid">>,
value => jsx:encode([?EXAMPLE_CLIENTID])
}
}
}
}
},
responses => #{ responses => #{
<<"204">> => #{description => <<"Created">>}, 204 => <<"Created">>,
<<"400">> => emqx_mgmt_util:bad_request() 400 => emqx_dashboard_swagger:error_codes( [?BAD_REQUEST]
, <<"Bad clientid or bad rule schema">>)
} }
} }
}, };
{"/authorization/sources/built-in-database/clientid", Metadata, clients}. schema("/authorization/sources/built-in-database/username/:username") ->
#{
user_api() -> 'operationId' => user,
Metadata = #{
get => #{ get => #{
description => "Get record info for username", tags => [<<"authorization">>],
parameters => [ description => <<"Get record info for username">>,
#{ parameters => [hoconsc:ref(username)],
name => username,
in => path,
schema => #{
type => string
},
required => true
}
],
responses => #{ responses => #{
<<"200">> => #{ 200 => swagger_with_example( {rules_for_username, ?TYPE_REF}
description => <<"OK">>, , {username, ?PUT_MAP_EXAMPLE}),
content => #{ 404 => emqx_dashboard_swagger:error_codes([?NOT_FOUND], <<"Not Found">>)
'application/json' => #{
schema => minirest:ref(<<"username">>),
examples => #{
username => #{
summary => <<"Username">>,
value => jsx:encode(?EXAMPLE_USERNAME)
}
}
}
}
},
<<"404">> => emqx_mgmt_util:bad_request(<<"Not Found">>)
} }
}, },
put => #{ put => #{
description => "Set record for username", tags => [<<"authorization">>],
parameters => [ description => <<"Set record for username">>,
#{ parameters => [hoconsc:ref(username)],
name => username, 'requestBody' => swagger_with_example( {rules_for_username, ?TYPE_REF}
in => path, , {username, ?PUT_MAP_EXAMPLE}),
schema => #{
type => string
},
required => true
}
],
requestBody => #{
content => #{
'application/json' => #{
schema => minirest:ref(<<"username">>),
examples => #{
username => #{
summary => <<"Username">>,
value => jsx:encode(?EXAMPLE_USERNAME)
}
}
}
}
},
responses => #{ responses => #{
<<"204">> => #{description => <<"Updated">>}, 204 => <<"Updated">>,
<<"400">> => emqx_mgmt_util:bad_request() 400 => emqx_dashboard_swagger:error_codes( [?BAD_REQUEST]
, <<"Bad username or bad rule schema">>)
} }
}, },
delete => #{ delete => #{
description => "Delete one record for username", tags => [<<"authorization">>],
parameters => [ description => <<"Delete one record for username">>,
#{ parameters => [hoconsc:ref(username)],
name => username,
in => path,
schema => #{
type => string
},
required => true
}
],
responses => #{ responses => #{
<<"204">> => #{description => <<"No Content">>}, 204 => <<"No Content">>,
<<"400">> => emqx_mgmt_util:bad_request() 400 => emqx_dashboard_swagger:error_codes([?BAD_REQUEST], <<"Bad username">>)
} }
} }
}, };
{"/authorization/sources/built-in-database/username/:username", Metadata, user}. schema("/authorization/sources/built-in-database/clientid/:clientid") ->
#{
client_api() -> 'operationId' => client,
Metadata = #{
get => #{ get => #{
description => "Get record info for clientid", tags => [<<"authorization">>],
parameters => [ description => <<"Get record info for clientid">>,
#{ parameters => [hoconsc:ref(clientid)],
name => clientid,
in => path,
schema => #{
type => string
},
required => true
}
],
responses => #{ responses => #{
<<"200">> => #{ 200 => swagger_with_example( {rules_for_clientid, ?TYPE_REF}
description => <<"OK">>, , {clientid, ?PUT_MAP_EXAMPLE}),
content => #{ 404 => emqx_dashboard_swagger:error_codes([?NOT_FOUND], <<"Not Found">>)
'application/json' => #{
schema => minirest:ref(<<"clientid">>),
examples => #{
clientid => #{
summary => <<"Clientid">>,
value => jsx:encode(?EXAMPLE_CLIENTID)
}
}
}
}
},
<<"404">> => emqx_mgmt_util:bad_request(<<"Not Found">>)
} }
}, },
put => #{ put => #{
description => "Set record for clientid", tags => [<<"authorization">>],
parameters => [ description => <<"Set record for clientid">>,
#{ parameters => [hoconsc:ref(clientid)],
name => clientid, 'requestBody' => swagger_with_example( {rules_for_clientid, ?TYPE_REF}
in => path, , {clientid, ?PUT_MAP_EXAMPLE}),
schema => #{
type => string
},
required => true
}
],
requestBody => #{
content => #{
'application/json' => #{
schema => minirest:ref(<<"clientid">>),
examples => #{
clientid => #{
summary => <<"Clientid">>,
value => jsx:encode(?EXAMPLE_CLIENTID)
}
}
}
}
},
responses => #{ responses => #{
<<"204">> => #{description => <<"Updated">>}, 204 => <<"Updated">>,
<<"400">> => emqx_mgmt_util:bad_request() 400 => emqx_dashboard_swagger:error_codes(
[?BAD_REQUEST], <<"Bad clientid or bad rule schema">>)
} }
}, },
delete => #{ delete => #{
description => "Delete one record for clientid", tags => [<<"authorization">>],
parameters => [ description => <<"Delete one record for clientid">>,
#{ parameters => [hoconsc:ref(clientid)],
name => clientid,
in => path,
schema => #{
type => string
},
required => true
}
],
responses => #{ responses => #{
<<"204">> => #{description => <<"No Content">>}, 204 => <<"No Content">>,
<<"400">> => emqx_mgmt_util:bad_request() 400 => emqx_dashboard_swagger:error_codes([?BAD_REQUEST], <<"Bad clientid">>)
} }
} }
}, };
{"/authorization/sources/built-in-database/clientid/:clientid", Metadata, client}. schema("/authorization/sources/built-in-database/all") ->
#{
all_api() -> 'operationId' => all,
Metadata = #{
get => #{ get => #{
description => "Show the list of rules for all", tags => [<<"authorization">>],
description => <<"Show the list of rules for all">>,
responses => #{ responses => #{
<<"200">> => #{ 200 => swagger_with_example({rules_for_all, ?TYPE_REF}, {all, ?PUT_MAP_EXAMPLE})
description => <<"OK">>,
content => #{
'application/json' => #{
schema => minirest:ref(<<"clientid">>),
examples => #{
clientid => #{
summary => <<"All">>,
value => jsx:encode(?EXAMPLE_ALL)
}
}
}
}
}
} }
}, },
put => #{ put => #{
description => "Set the list of rules for all", tags => [<<"authorization">>],
requestBody => #{ description => <<"Set the list of rules for all">>,
content => #{ 'requestBody' =>
'application/json' => #{ swagger_with_example({rules_for_all, ?TYPE_REF}, {all, ?PUT_MAP_EXAMPLE}),
schema => minirest:ref(<<"all">>),
examples => #{
all => #{
summary => <<"All">>,
value => jsx:encode(?EXAMPLE_ALL)
}
}
}
}
},
responses => #{ responses => #{
<<"204">> => #{description => <<"Created">>}, 204 => <<"Created">>,
<<"400">> => emqx_mgmt_util:bad_request() 400 => emqx_dashboard_swagger:error_codes([?BAD_REQUEST], <<"Bad rule schema">>)
} }
} }
}, };
{"/authorization/sources/built-in-database/all", Metadata, all}. schema("/authorization/sources/built-in-database/purge-all") ->
#{
purge_api() -> 'operationId' => purge,
Metadata = #{
delete => #{ delete => #{
description => "Purge all records", tags => [<<"authorization">>],
description => <<"Purge all records">>,
responses => #{ responses => #{
<<"204">> => #{description => <<"No Content">>}, 204 => <<"No Content">>,
<<"400">> => emqx_mgmt_util:bad_request() 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}) -> users(get, #{query_string := PageParams}) ->
MatchSpec = ets:fun2ms( MatchSpec = ets:fun2ms(
@ -609,7 +369,8 @@ purge(delete, _) ->
{204}; {204};
[#{<<"enable">> := true}] -> [#{<<"enable">> := true}] ->
{400, #{code => <<"BAD_REQUEST">>, {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">>, {404, #{code => <<"BAD_REQUEST">>,
message => <<"'built-in-database' type source is not found.">> 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) -> atom(B) when is_binary(B) ->
try binary_to_existing_atom(B, utf8) try binary_to_existing_atom(B, utf8)
catch catch
_ -> binary_to_atom(B) _Error:_Expection -> binary_to_atom(B)
end; end;
atom(A) when is_atom(A) -> A. 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(API_VERSION, "v5").
-define(BASE_PATH, "api"). -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"]. roots() -> ["authorization"].
@ -126,65 +82,149 @@ set_special_configs(_App) ->
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------
t_api(_) -> t_api(_) ->
{ok, 204, _} = request(post, uri(["authorization", "sources", "built-in-database", "username"]), [?EXAMPLE_USERNAME]), {ok, 204, _} =
{ok, 200, Request1} = request(get, uri(["authorization", "sources", "built-in-database", "username"]), []), request( post
{ok, 200, Request2} = request(get, uri(["authorization", "sources", "built-in-database", "username", "user1"]), []), , 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}], #{<<"data">> := [#{<<"username">> := <<"user1">>, <<"rules">> := Rules1}],
<<"meta">> := #{<<"count">> := 1,<<"limit">> := 100,<<"page">> := 1}} = jsx:decode(Request1), <<"meta">> := #{<<"count">> := 1,<<"limit">> := 100,<<"page">> := 1}} = jsx:decode(Request1),
#{<<"username">> := <<"user1">>, <<"rules">> := Rules1} = jsx:decode(Request2), #{<<"username">> := <<"user1">>, <<"rules">> := Rules1} = jsx:decode(Request2),
?assertEqual(3, length(Rules1)), ?assertEqual(3, length(Rules1)),
{ok, 204, _} = request(put, uri(["authorization", "sources", "built-in-database", "username", "user1"]), ?EXAMPLE_USERNAME#{rules => []}), {ok, 204, _} =
{ok, 200, Request3} = request(get, uri(["authorization", "sources", "built-in-database", "username", "user1"]), []), 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), #{<<"username">> := <<"user1">>, <<"rules">> := Rules2} = jsx:decode(Request3),
?assertEqual(0, length(Rules2)), ?assertEqual(0, length(Rules2)),
{ok, 204, _} = request(delete, uri(["authorization", "sources", "built-in-database", "username", "user1"]), []), {ok, 204, _} =
{ok, 404, _} = request(get, uri(["authorization", "sources", "built-in-database", "username", "user1"]), []), 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, 204, _} =
{ok, 200, Request4} = request(get, uri(["authorization", "sources", "built-in-database", "clientid"]), []), request( post
{ok, 200, Request5} = request(get, uri(["authorization", "sources", "built-in-database", "clientid", "client1"]), []), , 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}], #{<<"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), #{<<"clientid">> := <<"client1">>, <<"rules">> := Rules3} = jsx:decode(Request5),
?assertEqual(3, length(Rules3)), ?assertEqual(3, length(Rules3)),
{ok, 204, _} = request(put, uri(["authorization", "sources", "built-in-database", "clientid", "client1"]), ?EXAMPLE_CLIENTID#{rules => []}), {ok, 204, _} =
{ok, 200, Request6} = request(get, uri(["authorization", "sources", "built-in-database", "clientid", "client1"]), []), 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), #{<<"clientid">> := <<"client1">>, <<"rules">> := Rules4} = jsx:decode(Request6),
?assertEqual(0, length(Rules4)), ?assertEqual(0, length(Rules4)),
{ok, 204, _} = request(delete, uri(["authorization", "sources", "built-in-database", "clientid", "client1"]), []), {ok, 204, _} =
{ok, 404, _} = request(get, uri(["authorization", "sources", "built-in-database", "clientid", "client1"]), []), 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, 204, _} =
{ok, 200, Request7} = request(get, uri(["authorization", "sources", "built-in-database", "all"]), []), 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), #{<<"rules">> := Rules5} = jsx:decode(Request7),
?assertEqual(3, length(Rules5)), ?assertEqual(3, length(Rules5)),
{ok, 204, _} = request(put, uri(["authorization", "sources", "built-in-database", "all"]), ?EXAMPLE_ALL#{rules => []}), {ok, 204, _} =
{ok, 200, Request8} = request(get, uri(["authorization", "sources", "built-in-database", "all"]), []), 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), #{<<"rules">> := Rules6} = jsx:decode(Request8),
?assertEqual(0, length(Rules6)), ?assertEqual(0, length(Rules6)),
{ok, 204, _} = request(post, uri(["authorization", "sources", "built-in-database", "username"]), [ #{username => N, rules => []} || N <- lists:seq(1, 20) ]), {ok, 204, _} =
{ok, 200, Request9} = request(get, uri(["authorization", "sources", "built-in-database", "username?page=2&limit=5"]), []), 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), #{<<"data">> := Data1} = jsx:decode(Request9),
?assertEqual(5, length(Data1)), ?assertEqual(5, length(Data1)),
{ok, 204, _} = request(post, uri(["authorization", "sources", "built-in-database", "clientid"]), [ #{clientid => N, rules => []} || N <- lists:seq(1, 20) ]), {ok, 204, _} =
{ok, 200, Request10} = request(get, uri(["authorization", "sources", "built-in-database", "clientid?limit=5"]), []), 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), #{<<"data">> := Data2} = jsx:decode(Request10),
?assertEqual(5, length(Data2)), ?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")), ?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 %% test idempotence
{ok, 204, _} = request(put, uri(["authorization", "sources", "built-in-database"]), #{<<"enable">> => true}), {ok, 204, _} =
{ok, 204, _} = request(put, uri(["authorization", "sources", "built-in-database"]), #{<<"enable">> => false}), request( put
{ok, 204, _} = request(delete, uri(["authorization", "sources", "built-in-database", "purge-all"]), []), , 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)), ?assertEqual([], mnesia:dirty_all_keys(?ACL_TABLE)),
ok. ok.