support Seq
This commit is contained in:
parent
ea564ec8ef
commit
9bad2bf65b
|
@ -24,7 +24,6 @@
|
||||||
%%%
|
%%%
|
||||||
%%% @end
|
%%% @end
|
||||||
%%%-----------------------------------------------------------------------------
|
%%%-----------------------------------------------------------------------------
|
||||||
|
|
||||||
-module(emqttd_access_control).
|
-module(emqttd_access_control).
|
||||||
|
|
||||||
-author("Feng Lee <feng@emqtt.io>").
|
-author("Feng Lee <feng@emqtt.io>").
|
||||||
|
@ -36,14 +35,13 @@
|
||||||
-define(SERVER, ?MODULE).
|
-define(SERVER, ?MODULE).
|
||||||
|
|
||||||
%% API Function Exports
|
%% API Function Exports
|
||||||
-export([start_link/0,
|
-export([start_link/0, start_link/1,
|
||||||
start_link/1,
|
|
||||||
auth/2, % authentication
|
auth/2, % authentication
|
||||||
check_acl/3, % acl check
|
check_acl/3, % acl check
|
||||||
reload_acl/0, % reload acl
|
reload_acl/0, % reload acl
|
||||||
register_mod/3,
|
|
||||||
unregister_mod/2,
|
|
||||||
lookup_mods/1,
|
lookup_mods/1,
|
||||||
|
register_mod/3, register_mod/4,
|
||||||
|
unregister_mod/2,
|
||||||
stop/0]).
|
stop/0]).
|
||||||
|
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
|
@ -77,7 +75,7 @@ auth(Client, Password) when is_record(Client, mqtt_client) ->
|
||||||
auth(Client, Password, lookup_mods(auth)).
|
auth(Client, Password, lookup_mods(auth)).
|
||||||
auth(_Client, _Password, []) ->
|
auth(_Client, _Password, []) ->
|
||||||
{error, "No auth module to check!"};
|
{error, "No auth module to check!"};
|
||||||
auth(Client, Password, [{Mod, State} | Mods]) ->
|
auth(Client, Password, [{Mod, State, _Seq} | Mods]) ->
|
||||||
case Mod:check(Client, Password, State) of
|
case Mod:check(Client, Password, State) of
|
||||||
ok -> ok;
|
ok -> ok;
|
||||||
{error, Reason} -> {error, Reason};
|
{error, Reason} -> {error, Reason};
|
||||||
|
@ -100,7 +98,7 @@ check_acl(Client, PubSub, Topic) when ?IS_PUBSUB(PubSub) ->
|
||||||
check_acl(#mqtt_client{client_id = ClientId}, PubSub, Topic, []) ->
|
check_acl(#mqtt_client{client_id = ClientId}, PubSub, Topic, []) ->
|
||||||
lager:error("ACL: nomatch when ~s ~s ~s", [ClientId, PubSub, Topic]),
|
lager:error("ACL: nomatch when ~s ~s ~s", [ClientId, PubSub, Topic]),
|
||||||
allow;
|
allow;
|
||||||
check_acl(Client, PubSub, Topic, [{M, State}|AclMods]) ->
|
check_acl(Client, PubSub, Topic, [{M, State, _Seq}|AclMods]) ->
|
||||||
case M:check_acl({Client, PubSub, Topic}, State) of
|
case M:check_acl({Client, PubSub, Topic}, State) of
|
||||||
allow -> allow;
|
allow -> allow;
|
||||||
deny -> deny;
|
deny -> deny;
|
||||||
|
@ -113,7 +111,7 @@ check_acl(Client, PubSub, Topic, [{M, State}|AclMods]) ->
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
-spec reload_acl() -> list() | {error, any()}.
|
-spec reload_acl() -> list() | {error, any()}.
|
||||||
reload_acl() ->
|
reload_acl() ->
|
||||||
[M:reload_acl(State) || {M, State} <- lookup_mods(acl)].
|
[M:reload_acl(State) || {M, State, _Seq} <- lookup_mods(acl)].
|
||||||
|
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
%% @doc Register authentication or ACL module
|
%% @doc Register authentication or ACL module
|
||||||
|
@ -121,7 +119,11 @@ reload_acl() ->
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
-spec register_mod(Type :: auth | acl, Mod :: atom(), Opts :: list()) -> ok | {error, any()}.
|
-spec register_mod(Type :: auth | acl, Mod :: atom(), Opts :: list()) -> ok | {error, any()}.
|
||||||
register_mod(Type, Mod, Opts) when Type =:= auth; Type =:= acl->
|
register_mod(Type, Mod, Opts) when Type =:= auth; Type =:= acl->
|
||||||
gen_server:call(?SERVER, {register_mod, Type, Mod, Opts}).
|
register_mod(Type, Mod, Opts, 0).
|
||||||
|
|
||||||
|
-spec register_mod(auth | acl, atom(), list(), pos_integer()) -> ok | {error, any()}.
|
||||||
|
register_mod(Type, Mod, Opts, Seq) when Type =:= auth; Type =:= acl->
|
||||||
|
gen_server:call(?SERVER, {register_mod, Type, Mod, Opts, Seq}).
|
||||||
|
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
%% @doc Unregister authentication or ACL module
|
%% @doc Unregister authentication or ACL module
|
||||||
|
@ -172,16 +174,20 @@ init_mods(acl, AclMods) ->
|
||||||
init_mod(Fun, Name, Opts) ->
|
init_mod(Fun, Name, Opts) ->
|
||||||
Module = Fun(Name),
|
Module = Fun(Name),
|
||||||
{ok, State} = Module:init(Opts),
|
{ok, State} = Module:init(Opts),
|
||||||
{Module, State}.
|
{Module, State, 0}.
|
||||||
|
|
||||||
handle_call({register_mod, Type, Mod, Opts}, _From, State) ->
|
handle_call({register_mod, Type, Mod, Opts, Seq}, _From, State) ->
|
||||||
Mods = lookup_mods(Type),
|
Mods = lookup_mods(Type),
|
||||||
Reply =
|
Reply =
|
||||||
case lists:keyfind(Mod, 1, Mods) of
|
case lists:keyfind(Mod, 1, Mods) of
|
||||||
false ->
|
false ->
|
||||||
case catch Mod:init(Opts) of
|
case catch Mod:init(Opts) of
|
||||||
{ok, ModState} ->
|
{ok, ModState} ->
|
||||||
ets:insert(?ACCESS_CONTROL_TAB, {tab_key(Type), [{Mod, ModState}|Mods]}),
|
NewMods =
|
||||||
|
lists:sort(fun({_, _, Seq1}, {_, _, Seq2}) ->
|
||||||
|
Seq1 >= Seq2
|
||||||
|
end, [{Mod, ModState, Seq} | Mods]),
|
||||||
|
ets:insert(?ACCESS_CONTROL_TAB, {tab_key(Type), NewMods}),
|
||||||
ok;
|
ok;
|
||||||
{'EXIT', Error} ->
|
{'EXIT', Error} ->
|
||||||
lager:error("Access Control: register ~s error - ~p", [Mod, Error]),
|
lager:error("Access Control: register ~s error - ~p", [Mod, Error]),
|
||||||
|
|
|
@ -42,10 +42,13 @@ register_mod_test() ->
|
||||||
with_acl(
|
with_acl(
|
||||||
fun() ->
|
fun() ->
|
||||||
emqttd_access_control:register_mod(acl, emqttd_acl_test_mod, []),
|
emqttd_access_control:register_mod(acl, emqttd_acl_test_mod, []),
|
||||||
?assertMatch([{emqttd_acl_test_mod, _}, {emqttd_acl_internal, _}],
|
?assertMatch([{emqttd_acl_test_mod, _, 0}, {emqttd_acl_internal, _, 0}],
|
||||||
emqttd_access_control:lookup_mods(acl)),
|
emqttd_access_control:lookup_mods(acl)),
|
||||||
emqttd_access_control:register_mod(auth, emqttd_auth_anonymous_test_mod,[]),
|
emqttd_access_control:register_mod(auth, emqttd_auth_anonymous_test_mod,[]),
|
||||||
?assertMatch([{emqttd_auth_anonymous_test_mod, _}, {emqttd_auth_anonymous, _}],
|
emqttd_access_control:register_mod(auth, emqttd_auth_dashboard, [], 99),
|
||||||
|
?assertMatch([{emqttd_auth_dashboard, _, 99},
|
||||||
|
{emqttd_auth_anonymous_test_mod, _, 0},
|
||||||
|
{emqttd_auth_anonymous, _, 0}],
|
||||||
emqttd_access_control:lookup_mods(auth))
|
emqttd_access_control:lookup_mods(auth))
|
||||||
end).
|
end).
|
||||||
|
|
||||||
|
@ -53,19 +56,19 @@ unregister_mod_test() ->
|
||||||
with_acl(
|
with_acl(
|
||||||
fun() ->
|
fun() ->
|
||||||
emqttd_access_control:register_mod(acl, emqttd_acl_test_mod, []),
|
emqttd_access_control:register_mod(acl, emqttd_acl_test_mod, []),
|
||||||
?assertMatch([{emqttd_acl_test_mod, _}, {emqttd_acl_internal, _}],
|
?assertMatch([{emqttd_acl_test_mod, _, 0}, {emqttd_acl_internal, _, 0}],
|
||||||
emqttd_access_control:lookup_mods(acl)),
|
emqttd_access_control:lookup_mods(acl)),
|
||||||
emqttd_access_control:unregister_mod(acl, emqttd_acl_test_mod),
|
emqttd_access_control:unregister_mod(acl, emqttd_acl_test_mod),
|
||||||
timer:sleep(5),
|
timer:sleep(5),
|
||||||
?assertMatch([{emqttd_acl_internal, _}], emqttd_access_control:lookup_mods(acl)),
|
?assertMatch([{emqttd_acl_internal, _, 0}], emqttd_access_control:lookup_mods(acl)),
|
||||||
|
|
||||||
emqttd_access_control:register_mod(auth, emqttd_auth_anonymous_test_mod,[]),
|
emqttd_access_control:register_mod(auth, emqttd_auth_anonymous_test_mod,[]),
|
||||||
?assertMatch([{emqttd_auth_anonymous_test_mod, _}, {emqttd_auth_anonymous, _}],
|
?assertMatch([{emqttd_auth_anonymous_test_mod, _, 0}, {emqttd_auth_anonymous, _, 0}],
|
||||||
emqttd_access_control:lookup_mods(auth)),
|
emqttd_access_control:lookup_mods(auth)),
|
||||||
|
|
||||||
emqttd_access_control:unregister_mod(auth, emqttd_auth_anonymous_test_mod),
|
emqttd_access_control:unregister_mod(auth, emqttd_auth_anonymous_test_mod),
|
||||||
timer:sleep(5),
|
timer:sleep(5),
|
||||||
?assertMatch([{emqttd_auth_anonymous, _}], emqttd_access_control:lookup_mods(auth))
|
?assertMatch([{emqttd_auth_anonymous, _, 0}], emqttd_access_control:lookup_mods(auth))
|
||||||
end).
|
end).
|
||||||
|
|
||||||
check_acl_test() ->
|
check_acl_test() ->
|
||||||
|
|
Loading…
Reference in New Issue