summaryrefslogtreecommitdiff
path: root/src/acl.erl
diff options
context:
space:
mode:
authorEvgeny Khramtsov <ekhramtsov@process-one.net>2019-11-15 18:21:30 +0300
committerEvgeny Khramtsov <ekhramtsov@process-one.net>2019-11-15 18:21:30 +0300
commit33a16090d392e29f15274312059532fe97d731f6 (patch)
treea6a7413f42469c8a91ed64aff88e0731edd9a5a2 /src/acl.erl
parentBump yconf version (diff)
Fix acl reloading
Diffstat (limited to 'src/acl.erl')
-rw-r--r--src/acl.erl53
1 files changed, 28 insertions, 25 deletions
diff --git a/src/acl.erl b/src/acl.erl
index 054fad36..cf6861a6 100644
--- a/src/acl.erl
+++ b/src/acl.erl
@@ -169,17 +169,17 @@ validator(acl) ->
%%%===================================================================
-spec init([]) -> {ok, state()}.
init([]) ->
- create_tab(acl, bag),
- create_tab(access, set),
+ create_tab(acl),
+ create_tab(access),
Hosts = ejabberd_option:hosts(),
- load_from_config([], Hosts),
+ load_from_config(Hosts),
ejabberd_hooks:add(config_reloaded, ?MODULE, reload_from_config, 20),
{ok, #{hosts => Hosts}}.
-spec handle_call(term(), term(), state()) -> {reply, ok, state()} | {noreply, state()}.
-handle_call(reload_from_config, _, #{hosts := OldHosts} = State) ->
+handle_call(reload_from_config, _, State) ->
NewHosts = ejabberd_option:hosts(),
- load_from_config(OldHosts, NewHosts),
+ load_from_config(NewHosts),
{reply, ok, State#{hosts => NewHosts}};
handle_call(Request, From, State) ->
?WARNING_MSG("Unexpected call from ~p: ~p", [From, Request]),
@@ -209,31 +209,33 @@ code_change(_OldVsn, State, _Extra) ->
%%%===================================================================
%%% Table management
%%%===================================================================
--spec load_from_config([binary()], [binary()]) -> ok.
-load_from_config(OldHosts, NewHosts) ->
+-spec load_from_config([binary()]) -> ok.
+load_from_config(NewHosts) ->
?DEBUG("Loading access rules from config", []),
load_tab(acl, NewHosts, fun ejabberd_option:acl/1),
load_tab(access, NewHosts, fun ejabberd_option:access_rules/1),
- lists:foreach(
- fun(Host) ->
- ets:match_delete(access, {{'_', Host}, '_'}),
- ets:match_delete(acl, {{'_', Host}, '_'})
- end, OldHosts -- NewHosts),
?DEBUG("Access rules loaded successfully", []).
--spec create_tab(atom(), set | bag) -> atom().
-create_tab(Tab, Type) ->
+-spec create_tab(atom()) -> atom().
+create_tab(Tab) ->
_ = mnesia:delete_table(Tab),
- ets:new(Tab, [named_table, Type, {read_concurrency, true}]).
+ ets:new(Tab, [named_table, set, {read_concurrency, true}]).
--spec load_tab(atom(), [binary()], fun((global | binary()) -> {atom(), list()})) -> true.
+-spec load_tab(atom(), [binary()], fun((global | binary()) -> {atom(), list()})) -> ok.
load_tab(Tab, Hosts, Fun) ->
- ets:insert(
- Tab,
- lists:flatmap(
- fun(Host) ->
- [{{Name, Host}, List} || {Name, List} <- Fun(Host)]
- end, [global|Hosts])).
+ Old = ets:tab2list(Tab),
+ New = lists:flatmap(
+ fun(Host) ->
+ [{{Name, Host}, List} || {Name, List} <- Fun(Host)]
+ end, [global|Hosts]),
+ ets:insert(Tab, New),
+ lists:foreach(
+ fun({Key, _}) ->
+ case lists:keymember(Key, 1, New) of
+ false -> ets:delete(Tab, Key);
+ true -> ok
+ end
+ end, Old).
-spec read_access(atom(), global | binary()) -> access().
read_access(Name, Host) ->
@@ -244,9 +246,10 @@ read_access(Name, Host) ->
-spec read_acl(atom(), global | binary()) -> [acl_rule()].
read_acl(Name, Host) ->
- lists:flatmap(
- fun({_, ACL}) -> ACL end,
- ets:lookup(acl, {Name, Host})).
+ case ets:lookup(acl, {Name, Host}) of
+ [{_, ACL}] -> ACL;
+ [] -> []
+ end.
%%%===================================================================
%%% Validators