support Seq

This commit is contained in:
Feng 2015-11-03 12:52:27 +08:00
parent ea564ec8ef
commit 9bad2bf65b
2 changed files with 33 additions and 24 deletions

View File

@ -24,7 +24,6 @@
%%%
%%% @end
%%%-----------------------------------------------------------------------------
-module(emqttd_access_control).
-author("Feng Lee <feng@emqtt.io>").
@ -36,14 +35,13 @@
-define(SERVER, ?MODULE).
%% API Function Exports
-export([start_link/0,
start_link/1,
-export([start_link/0, start_link/1,
auth/2, % authentication
check_acl/3, % acl check
reload_acl/0, % reload acl
register_mod/3,
unregister_mod/2,
lookup_mods/1,
register_mod/3, register_mod/4,
unregister_mod/2,
stop/0]).
%% 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, []) ->
{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
ok -> ok;
{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, []) ->
lager:error("ACL: nomatch when ~s ~s ~s", [ClientId, PubSub, Topic]),
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
allow -> allow;
deny -> deny;
@ -113,7 +111,7 @@ check_acl(Client, PubSub, Topic, [{M, State}|AclMods]) ->
%%------------------------------------------------------------------------------
-spec reload_acl() -> list() | {error, any()}.
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
@ -121,7 +119,11 @@ reload_acl() ->
%%------------------------------------------------------------------------------
-spec register_mod(Type :: auth | acl, Mod :: atom(), Opts :: list()) -> ok | {error, any()}.
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
@ -172,22 +174,26 @@ init_mods(acl, AclMods) ->
init_mod(Fun, Name, Opts) ->
Module = Fun(Name),
{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),
Reply =
case lists:keyfind(Mod, 1, Mods) of
false ->
false ->
case catch Mod:init(Opts) of
{ok, ModState} ->
ets:insert(?ACCESS_CONTROL_TAB, {tab_key(Type), [{Mod, ModState}|Mods]}),
{ok, ModState} ->
NewMods =
lists:sort(fun({_, _, Seq1}, {_, _, Seq2}) ->
Seq1 >= Seq2
end, [{Mod, ModState, Seq} | Mods]),
ets:insert(?ACCESS_CONTROL_TAB, {tab_key(Type), NewMods}),
ok;
{'EXIT', Error} ->
lager:error("Access Control: register ~s error - ~p", [Mod, Error]),
{error, Error}
end;
_ ->
_ ->
{error, existed}
end,
{reply, Reply, State};

View File

@ -42,30 +42,33 @@ register_mod_test() ->
with_acl(
fun() ->
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:register_mod(auth, emqttd_auth_anonymous_test_mod,[]),
?assertMatch([{emqttd_auth_anonymous_test_mod, _}, {emqttd_auth_anonymous, _}],
emqttd_access_control:lookup_mods(auth))
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))
end).
unregister_mod_test() ->
with_acl(
fun() ->
emqttd_access_control:register_mod(acl,emqttd_acl_test_mod, []),
?assertMatch([{emqttd_acl_test_mod, _}, {emqttd_acl_internal, _}],
emqttd_access_control:register_mod(acl, emqttd_acl_test_mod, []),
?assertMatch([{emqttd_acl_test_mod, _, 0}, {emqttd_acl_internal, _, 0}],
emqttd_access_control:lookup_mods(acl)),
emqttd_access_control:unregister_mod(acl, emqttd_acl_test_mod),
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,[]),
?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:unregister_mod(auth, emqttd_auth_anonymous_test_mod),
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).
check_acl_test() ->
@ -83,7 +86,7 @@ check_acl_test() ->
with_acl(Fun) ->
process_flag(trap_exit, true),
AclOpts = [
AclOpts = [
{auth, [
%% Authentication with username, password
%{username, []},