Stefan Strigler 2 лет назад
Родитель
Сommit
ea9228108b

+ 148 - 175
apps/emqx_auth_mnesia/src/emqx_authz_api_mnesia.erl

@@ -18,6 +18,7 @@
 
 -behaviour(minirest_api).
 
+-include("emqx_auth_mnesia.hrl").
 -include_lib("emqx_auth/include/emqx_authz.hrl").
 -include_lib("emqx/include/logger.hrl").
 -include_lib("hocon/include/hoconsc.hrl").
@@ -55,6 +56,9 @@
     format_result/1
 ]).
 
+%% minirest filter callback
+-export([is_configured_authz_source/2]).
+
 -define(BAD_REQUEST, 'BAD_REQUEST').
 -define(NOT_FOUND, 'NOT_FOUND').
 -define(ALREADY_EXISTS, 'ALREADY_EXISTS').
@@ -85,6 +89,7 @@ paths() ->
 schema("/authorization/sources/built_in_database/rules/users") ->
     #{
         'operationId' => users,
+        filter => fun ?MODULE:is_configured_authz_source/2,
         get =>
             #{
                 tags => [<<"authorization">>],
@@ -131,6 +136,7 @@ schema("/authorization/sources/built_in_database/rules/users") ->
 schema("/authorization/sources/built_in_database/rules/clients") ->
     #{
         'operationId' => clients,
+        filter => fun ?MODULE:is_configured_authz_source/2,
         get =>
             #{
                 tags => [<<"authorization">>],
@@ -177,6 +183,7 @@ schema("/authorization/sources/built_in_database/rules/clients") ->
 schema("/authorization/sources/built_in_database/rules/users/:username") ->
     #{
         'operationId' => user,
+        filter => fun ?MODULE:is_configured_authz_source/2,
         get =>
             #{
                 tags => [<<"authorization">>],
@@ -230,6 +237,7 @@ schema("/authorization/sources/built_in_database/rules/users/:username") ->
 schema("/authorization/sources/built_in_database/rules/clients/:clientid") ->
     #{
         'operationId' => client,
+        filter => fun ?MODULE:is_configured_authz_source/2,
         get =>
             #{
                 tags => [<<"authorization">>],
@@ -283,6 +291,7 @@ schema("/authorization/sources/built_in_database/rules/clients/:clientid") ->
 schema("/authorization/sources/built_in_database/rules/all") ->
     #{
         'operationId' => all,
+        filter => fun ?MODULE:is_configured_authz_source/2,
         get =>
             #{
                 tags => [<<"authorization">>],
@@ -317,6 +326,7 @@ schema("/authorization/sources/built_in_database/rules/all") ->
 schema("/authorization/sources/built_in_database/rules") ->
     #{
         'operationId' => rules,
+        filter => fun ?MODULE:is_configured_authz_source/2,
         delete =>
             #{
                 tags => [<<"authorization">>],
@@ -426,210 +436,173 @@ fields(rules) ->
 %% HTTP API
 %%--------------------------------------------------------------------
 
--define(IF_CONFIGURED_AUTHZ_SOURCE(EXPR),
+is_configured_authz_source(Params, _Meta) ->
     emqx_authz_api_sources:with_source(
-        <<"built_in_database">>,
+        ?AUTHZ_TYPE_BIN,
         fun(_Source) ->
-            EXPR
+            {ok, Params}
         end
-    )
-).
+    ).
 
 users(get, #{query_string := QueryString}) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        case
-            emqx_mgmt_api:node_query(
-                node(),
-                ?ACL_TABLE,
-                QueryString,
-                ?ACL_USERNAME_QSCHEMA,
-                ?QUERY_USERNAME_FUN,
-                fun ?MODULE:format_result/1
-            )
-        of
-            {error, page_limit_invalid} ->
-                {400, #{code => <<"INVALID_PARAMETER">>, message => <<"page_limit_invalid">>}};
-            {error, Node, Error} ->
-                Message = list_to_binary(
-                    io_lib:format("bad rpc call ~p, Reason ~p", [Node, Error])
-                ),
-                {500, #{code => <<"NODE_DOWN">>, message => Message}};
-            Result ->
-                {200, Result}
-        end
-    );
+    case
+        emqx_mgmt_api:node_query(
+            node(),
+            ?ACL_TABLE,
+            QueryString,
+            ?ACL_USERNAME_QSCHEMA,
+            ?QUERY_USERNAME_FUN,
+            fun ?MODULE:format_result/1
+        )
+    of
+        {error, page_limit_invalid} ->
+            {400, #{code => <<"INVALID_PARAMETER">>, message => <<"page_limit_invalid">>}};
+        {error, Node, Error} ->
+            Message = list_to_binary(
+                io_lib:format("bad rpc call ~p, Reason ~p", [Node, Error])
+            ),
+            {500, #{code => <<"NODE_DOWN">>, message => Message}};
+        Result ->
+            {200, Result}
+    end;
 users(post, #{body := Body}) when is_list(Body) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        case ensure_all_not_exists(<<"username">>, username, Body) of
-            [] ->
-                lists:foreach(
-                    fun(#{<<"username">> := Username, <<"rules">> := Rules}) ->
-                        emqx_authz_mnesia:store_rules({username, Username}, Rules)
-                    end,
-                    Body
-                ),
-                {204};
-            Exists ->
-                {409, #{
-                    code => <<"ALREADY_EXISTS">>,
-                    message => binfmt("Users '~ts' already exist", [binjoin(Exists)])
-                }}
-        end
-    ).
+    case ensure_all_not_exists(<<"username">>, username, Body) of
+        [] ->
+            lists:foreach(
+                fun(#{<<"username">> := Username, <<"rules">> := Rules}) ->
+                    emqx_authz_mnesia:store_rules({username, Username}, Rules)
+                end,
+                Body
+            ),
+            {204};
+        Exists ->
+            {409, #{
+                code => <<"ALREADY_EXISTS">>,
+                message => binfmt("Users '~ts' already exist", [binjoin(Exists)])
+            }}
+    end.
 
 clients(get, #{query_string := QueryString}) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        case
-            emqx_mgmt_api:node_query(
-                node(),
-                ?ACL_TABLE,
-                QueryString,
-                ?ACL_CLIENTID_QSCHEMA,
-                ?QUERY_CLIENTID_FUN,
-                fun ?MODULE:format_result/1
-            )
-        of
-            {error, page_limit_invalid} ->
-                {400, #{code => <<"INVALID_PARAMETER">>, message => <<"page_limit_invalid">>}};
-            {error, Node, Error} ->
-                Message = list_to_binary(
-                    io_lib:format("bad rpc call ~p, Reason ~p", [Node, Error])
-                ),
-                {500, #{code => <<"NODE_DOWN">>, message => Message}};
-            Result ->
-                {200, Result}
-        end
-    );
+    case
+        emqx_mgmt_api:node_query(
+            node(),
+            ?ACL_TABLE,
+            QueryString,
+            ?ACL_CLIENTID_QSCHEMA,
+            ?QUERY_CLIENTID_FUN,
+            fun ?MODULE:format_result/1
+        )
+    of
+        {error, page_limit_invalid} ->
+            {400, #{code => <<"INVALID_PARAMETER">>, message => <<"page_limit_invalid">>}};
+        {error, Node, Error} ->
+            Message = list_to_binary(
+                io_lib:format("bad rpc call ~p, Reason ~p", [Node, Error])
+            ),
+            {500, #{code => <<"NODE_DOWN">>, message => Message}};
+        Result ->
+            {200, Result}
+    end;
 clients(post, #{body := Body}) when is_list(Body) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        case ensure_all_not_exists(<<"clientid">>, clientid, Body) of
-            [] ->
-                lists:foreach(
-                    fun(#{<<"clientid">> := ClientID, <<"rules">> := Rules}) ->
-                        emqx_authz_mnesia:store_rules({clientid, ClientID}, Rules)
-                    end,
-                    Body
-                ),
-                {204};
-            Exists ->
-                {409, #{
-                    code => <<"ALREADY_EXISTS">>,
-                    message => binfmt("Clients '~ts' already exist", [binjoin(Exists)])
-                }}
-        end
-    ).
+    case ensure_all_not_exists(<<"clientid">>, clientid, Body) of
+        [] ->
+            lists:foreach(
+                fun(#{<<"clientid">> := ClientID, <<"rules">> := Rules}) ->
+                    emqx_authz_mnesia:store_rules({clientid, ClientID}, Rules)
+                end,
+                Body
+            ),
+            {204};
+        Exists ->
+            {409, #{
+                code => <<"ALREADY_EXISTS">>,
+                message => binfmt("Clients '~ts' already exist", [binjoin(Exists)])
+            }}
+    end.
 
 user(get, #{bindings := #{username := Username}}) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        case emqx_authz_mnesia:get_rules({username, Username}) of
-            not_found ->
-                {404, #{code => <<"NOT_FOUND">>, message => <<"Not Found">>}};
-            {ok, Rules} ->
-                {200, #{
-                    username => Username,
-                    rules => format_rules(Rules)
-                }}
-        end
-    );
+    case emqx_authz_mnesia:get_rules({username, Username}) of
+        not_found ->
+            {404, #{code => <<"NOT_FOUND">>, message => <<"Not Found">>}};
+        {ok, Rules} ->
+            {200, #{
+                username => Username,
+                rules => format_rules(Rules)
+            }}
+    end;
 user(put, #{
     bindings := #{username := Username},
     body := #{<<"username">> := Username, <<"rules">> := Rules}
 }) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        begin
-            emqx_authz_mnesia:store_rules({username, Username}, Rules),
-            {204}
-        end
-    );
+    emqx_authz_mnesia:store_rules({username, Username}, Rules),
+    {204};
 user(delete, #{bindings := #{username := Username}}) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        case emqx_authz_mnesia:get_rules({username, Username}) of
-            not_found ->
-                {404, #{code => <<"NOT_FOUND">>, message => <<"Username Not Found">>}};
-            {ok, _Rules} ->
-                emqx_authz_mnesia:delete_rules({username, Username}),
-                {204}
-        end
-    ).
+    case emqx_authz_mnesia:get_rules({username, Username}) of
+        not_found ->
+            {404, #{code => <<"NOT_FOUND">>, message => <<"Username Not Found">>}};
+        {ok, _Rules} ->
+            emqx_authz_mnesia:delete_rules({username, Username}),
+            {204}
+    end.
 
 client(get, #{bindings := #{clientid := ClientID}}) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        case emqx_authz_mnesia:get_rules({clientid, ClientID}) of
-            not_found ->
-                {404, #{code => <<"NOT_FOUND">>, message => <<"Not Found">>}};
-            {ok, Rules} ->
-                {200, #{
-                    clientid => ClientID,
-                    rules => format_rules(Rules)
-                }}
-        end
-    );
+    case emqx_authz_mnesia:get_rules({clientid, ClientID}) of
+        not_found ->
+            {404, #{code => <<"NOT_FOUND">>, message => <<"Not Found">>}};
+        {ok, Rules} ->
+            {200, #{
+                clientid => ClientID,
+                rules => format_rules(Rules)
+            }}
+    end;
 client(put, #{
     bindings := #{clientid := ClientID},
     body := #{<<"clientid">> := ClientID, <<"rules">> := Rules}
 }) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        begin
-            emqx_authz_mnesia:store_rules({clientid, ClientID}, Rules),
-            {204}
-        end
-    );
+    emqx_authz_mnesia:store_rules({clientid, ClientID}, Rules),
+    {204};
 client(delete, #{bindings := #{clientid := ClientID}}) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        case emqx_authz_mnesia:get_rules({clientid, ClientID}) of
-            not_found ->
-                {404, #{code => <<"NOT_FOUND">>, message => <<"ClientID Not Found">>}};
-            {ok, _Rules} ->
-                emqx_authz_mnesia:delete_rules({clientid, ClientID}),
-                {204}
-        end
-    ).
+    case emqx_authz_mnesia:get_rules({clientid, ClientID}) of
+        not_found ->
+            {404, #{code => <<"NOT_FOUND">>, message => <<"ClientID Not Found">>}};
+        {ok, _Rules} ->
+            emqx_authz_mnesia:delete_rules({clientid, ClientID}),
+            {204}
+    end.
 
 all(get, _) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        case emqx_authz_mnesia:get_rules(all) of
-            not_found ->
-                {200, #{rules => []}};
-            {ok, Rules} ->
-                {200, #{
-                    rules => format_rules(Rules)
-                }}
-        end
-    );
+    case emqx_authz_mnesia:get_rules(all) of
+        not_found ->
+            {200, #{rules => []}};
+        {ok, Rules} ->
+            {200, #{
+                rules => format_rules(Rules)
+            }}
+    end;
 all(post, #{body := #{<<"rules">> := Rules}}) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        begin
-            emqx_authz_mnesia:store_rules(all, Rules),
-            {204}
-        end
-    );
+    emqx_authz_mnesia:store_rules(all, Rules),
+    {204};
 all(delete, _) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        begin
-            emqx_authz_mnesia:store_rules(all, []),
-            {204}
-        end
-    ).
+    emqx_authz_mnesia:store_rules(all, []),
+    {204}.
 
 rules(delete, _) ->
-    ?IF_CONFIGURED_AUTHZ_SOURCE(
-        case emqx_authz_api_sources:get_raw_source(<<"built_in_database">>) of
-            [#{<<"enable">> := false}] ->
-                ok = emqx_authz_mnesia:purge_rules(),
-                {204};
-            [#{<<"enable">> := true}] ->
-                {400, #{
-                    code => <<"BAD_REQUEST">>,
-                    message =>
-                        <<"'built_in_database' type source must be disabled before purge.">>
-                }};
-            [] ->
-                {404, #{
-                    code => <<"BAD_REQUEST">>,
-                    message => <<"'built_in_database' type source is not found.">>
-                }}
-        end
-    ).
+    case emqx_authz_api_sources:get_raw_source(<<"built_in_database">>) of
+        [#{<<"enable">> := false}] ->
+            ok = emqx_authz_mnesia:purge_rules(),
+            {204};
+        [#{<<"enable">> := true}] ->
+            {400, #{
+                code => <<"BAD_REQUEST">>,
+                message =>
+                    <<"'built_in_database' type source must be disabled before purge.">>
+            }};
+        [] ->
+            {404, #{
+                code => <<"BAD_REQUEST">>,
+                message => <<"'built_in_database' type source is not found.">>
+            }}
+    end.
 
 %%--------------------------------------------------------------------
 %% QueryString to MatchSpec

+ 6 - 2
apps/emqx_auth_mnesia/test/emqx_authz_api_mnesia_SUITE.erl

@@ -415,7 +415,9 @@ run_examples(Code, Examples) when is_number(Code) ->
     run_examples(
         fun
             ({ok, ResCode, _}) when Code =:= ResCode -> true;
-            (_) -> false
+            (_Res) ->
+                ct:pal("check failed: ~p", [_Res]),
+                false
         end,
         Examples
     ).
@@ -455,7 +457,9 @@ make_examples(ApiMod, Replacements) ->
                             end,
                         {replace_parts(to_parts(Path), Replacements), Op, Body}
                     end,
-                    lists:sort(fun op_sort/2, maps:to_list(maps:remove('operationId', Schema)))
+                    lists:sort(
+                        fun op_sort/2, maps:to_list(maps:with([get, put, post, delete], Schema))
+                    )
                 )
             end,
             Paths