88 lines
3.2 KiB
Erlang
88 lines
3.2 KiB
Erlang
%%--------------------------------------------------------------------
|
|
%% Copyright (c) 2020-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
|
|
%%
|
|
%% Licensed under the Apache License, Version 2.0 (the "License");
|
|
%% you may not use this file except in compliance with the License.
|
|
%% You may obtain a copy of the License at
|
|
%%
|
|
%% http://www.apache.org/licenses/LICENSE-2.0
|
|
%%
|
|
%% Unless required by applicable law or agreed to in writing, software
|
|
%% distributed under the License is distributed on an "AS IS" BASIS,
|
|
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
%% See the License for the specific language governing permissions and
|
|
%% limitations under the License.
|
|
%%--------------------------------------------------------------------
|
|
|
|
-module(emqx_acl_mnesia).
|
|
|
|
-include("emqx_auth_mnesia.hrl").
|
|
|
|
%% ACL Callbacks
|
|
-export([ init/0
|
|
, check_acl/5
|
|
, description/0
|
|
]).
|
|
|
|
init() ->
|
|
ok = emqx_acl_mnesia_db:create_table(),
|
|
ok = emqx_acl_mnesia_db:create_table2().
|
|
|
|
check_acl(ClientInfo = #{ clientid := Clientid }, PubSub, Topic, _NoMatchAction, _Params) ->
|
|
Username = maps:get(username, ClientInfo, undefined),
|
|
|
|
Acls = case Username of
|
|
undefined ->
|
|
emqx_acl_mnesia_db:lookup_acl({clientid, Clientid}) ++
|
|
emqx_acl_mnesia_db:lookup_acl(all);
|
|
_ ->
|
|
emqx_acl_mnesia_db:lookup_acl({clientid, Clientid}) ++
|
|
emqx_acl_mnesia_db:lookup_acl({username, Username}) ++
|
|
emqx_acl_mnesia_db:lookup_acl(all)
|
|
end,
|
|
|
|
case match(ClientInfo, PubSub, Topic, Acls) of
|
|
allow ->
|
|
{stop, allow};
|
|
deny ->
|
|
{stop, deny};
|
|
_ ->
|
|
ok
|
|
end.
|
|
|
|
description() -> "Acl with Mnesia".
|
|
|
|
%%--------------------------------------------------------------------
|
|
%% Internal functions
|
|
%%-------------------------------------------------------------------
|
|
|
|
match(_ClientInfo, _PubSub, _Topic, []) ->
|
|
nomatch;
|
|
match(ClientInfo, PubSub, Topic, [ {_, ACLTopic, Action, Access, _} | Acls]) ->
|
|
case match_actions(PubSub, Action) andalso match_topic(ClientInfo, Topic, ACLTopic) of
|
|
true -> Access;
|
|
false -> match(ClientInfo, PubSub, Topic, Acls)
|
|
end.
|
|
|
|
match_topic(ClientInfo, Topic, ACLTopic) when is_binary(Topic) ->
|
|
emqx_topic:match(Topic, feed_var(ClientInfo, ACLTopic)).
|
|
|
|
match_actions(subscribe, sub) -> true;
|
|
match_actions(publish, pub) -> true;
|
|
match_actions(_, _) -> false.
|
|
|
|
feed_var(ClientInfo, Pattern) ->
|
|
feed_var(ClientInfo, emqx_topic:words(Pattern), []).
|
|
feed_var(_ClientInfo, [], Acc) ->
|
|
emqx_topic:join(lists:reverse(Acc));
|
|
feed_var(ClientInfo = #{clientid := undefined}, [<<"%c">>|Words], Acc) ->
|
|
feed_var(ClientInfo, Words, [<<"%c">>|Acc]);
|
|
feed_var(ClientInfo = #{clientid := ClientId}, [<<"%c">>|Words], Acc) ->
|
|
feed_var(ClientInfo, Words, [ClientId |Acc]);
|
|
feed_var(ClientInfo = #{username := undefined}, [<<"%u">>|Words], Acc) ->
|
|
feed_var(ClientInfo, Words, [<<"%u">>|Acc]);
|
|
feed_var(ClientInfo = #{username := Username}, [<<"%u">>|Words], Acc) ->
|
|
feed_var(ClientInfo, Words, [Username|Acc]);
|
|
feed_var(ClientInfo, [W|Words], Acc) ->
|
|
feed_var(ClientInfo, Words, [W|Acc]).
|